├── .gitattributes ├── .gitignore ├── AppxActivate ├── AppxActivate.csproj ├── Program.cs └── Properties │ ├── AssemblyInfo.cs │ └── launchSettings.json ├── Dataviewer ├── AboutBox.designer.vb ├── AboutBox.resx ├── AboutBox.vb ├── Dataviewer.Designer.vb ├── Dataviewer.ico ├── Dataviewer.resx ├── Dataviewer.vb ├── Dataviewer.vbproj ├── My Project │ ├── Settings.Designer.vb │ ├── Settings.settings │ └── app.manifest └── Program.vb ├── Directory.Build.props ├── DiskVolumes ├── DiskVolumes.cs ├── DiskVolumes.csproj ├── Program.cs └── Properties │ └── AssemblyInfo.cs ├── GetProductKey ├── GetProductKey.csproj └── Program.cs ├── ImageMBR2GPT ├── ImageMBR2GPT.csproj ├── Program.cs └── Properties │ └── launchSettings.json ├── PowerShellFs ├── PowerShellFs.cs ├── PowerShellFs.csproj ├── Program.cs └── Properties │ ├── AssemblyInfo.cs │ └── launchSettings.json ├── RecentCleanup ├── Interop.IWshRuntimeLibrary.dll ├── Program.cs └── RecentCleanup.csproj ├── SessionPowerSaver ├── Program.cs └── SessionPowerSaver.csproj ├── StripeBlockSwap ├── Program.cs └── StripeBlockSwap.csproj ├── SystemTools.sln ├── dssearch ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── dssearch.csproj ├── ipcalc ├── Program.cs └── ipcalc.csproj ├── telnets ├── Program.cs └── telnets.csproj ├── waitps ├── Program.cs └── waitps.csproj └── waitwin ├── Program.cs └── waitwin.csproj /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio LightSwitch build output 298 | **/*.HTMLClient/GeneratedArtifacts 299 | **/*.DesktopClient/GeneratedArtifacts 300 | **/*.DesktopClient/ModelManifest.xml 301 | **/*.Server/GeneratedArtifacts 302 | **/*.Server/ModelManifest.xml 303 | _Pvt_Extensions 304 | 305 | # Paket dependency manager 306 | .paket/paket.exe 307 | paket-files/ 308 | 309 | # FAKE - F# Make 310 | .fake/ 311 | 312 | # CodeRush personal settings 313 | .cr/personal 314 | 315 | # Python Tools for Visual Studio (PTVS) 316 | __pycache__/ 317 | *.pyc 318 | 319 | # Cake - Uncomment if you are using it 320 | # tools/** 321 | # !tools/packages.config 322 | 323 | # Tabs Studio 324 | *.tss 325 | 326 | # Telerik's JustMock configuration file 327 | *.jmconfig 328 | 329 | # BizTalk build output 330 | *.btp.cs 331 | *.btm.cs 332 | *.odx.cs 333 | *.xsd.cs 334 | 335 | # OpenCover UI analysis results 336 | OpenCover/ 337 | 338 | # Azure Stream Analytics local run output 339 | ASALocalRun/ 340 | 341 | # MSBuild Binary and Structured Log 342 | *.binlog 343 | 344 | # NVidia Nsight GPU debugger configuration file 345 | *.nvuser 346 | 347 | # MFractors (Xamarin productivity tool) working folder 348 | .mfractor/ 349 | 350 | # Local History for Visual Studio 351 | .localhistory/ 352 | 353 | # BeatPulse healthcheck temp database 354 | healthchecksdb 355 | 356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 357 | MigrationBackup/ 358 | 359 | # Ionide (cross platform F# VS Code tools) working folder 360 | .ionide/ 361 | 362 | # Fody - auto-generated XML schema 363 | FodyWeavers.xsd 364 | 365 | **/launchSettings.json 366 | -------------------------------------------------------------------------------- /AppxActivate/AppxActivate.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Exe 6 | net46 7 | 8 | 9 | -------------------------------------------------------------------------------- /AppxActivate/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | using System.Linq; 5 | using System.Collections.Generic; 6 | 7 | namespace Win8; 8 | 9 | [ComImport, Guid("2e941141-7f97-4756-ba1d-9decde894a3d"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 10 | interface IApplicationActivationManager 11 | { 12 | IntPtr ActivateApplication(string appUserModelId, string arguments, uint options, out uint processId); 13 | } 14 | 15 | [ComImport, Guid("45BA127D-10A8-46EA-8AB7-56EA9078943C")]//Application Activation Manager 16 | public class ApplicationActivationManager : IApplicationActivationManager 17 | { 18 | [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)/*, PreserveSig*/] 19 | public extern IntPtr ActivateApplication(string appUserModelId, string? arguments, uint options, out uint processId); 20 | 21 | } 22 | 23 | public static class Program 24 | { 25 | private static IEnumerable EnumerateMessages(this Exception ex) 26 | { 27 | while (ex is not null) 28 | { 29 | yield return ex.Message; 30 | ex = ex.InnerException; 31 | } 32 | } 33 | 34 | public static int Main(params string[] args) 35 | { 36 | if (args is null || args.Length == 0) 37 | { 38 | Console.WriteLine("Package name required."); 39 | return -1; 40 | } 41 | 42 | try 43 | { 44 | var appman = new ApplicationActivationManager(); 45 | 46 | string? app_args = null; 47 | 48 | if (args.Length > 2) 49 | { 50 | app_args = string.Join(" ", args.Skip(1).Select(p => $"\"{p}\"")); 51 | } 52 | 53 | appman.ActivateApplication(args[0], 54 | app_args, 55 | 0, 56 | out var pid); 57 | 58 | return unchecked((int)pid); 59 | } 60 | catch (Exception ex) 61 | { 62 | Console.Error.WriteLine( 63 | string.Join(" -> ", ex.EnumerateMessages())); 64 | 65 | return ex.HResult; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /AppxActivate/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | // General Information about an assembly is controlled through the following 4 | // set of attributes. Change these attribute values to modify the information 5 | // associated with an assembly. 6 | 7 | // Setting ComVisible to false makes the types in this assembly not visible 8 | // to COM components. If you need to access a type in this assembly from 9 | // COM, set the ComVisible attribute to true on that type. 10 | [assembly: ComVisible(false)] 11 | 12 | // The following GUID is for the ID of the typelib if this project is exposed to COM 13 | [assembly: Guid("dd6c6e70-2c81-486d-96cc-df0282056502")] 14 | 15 | // Version information for an assembly consists of the following four values: 16 | // 17 | // Major Version 18 | // Minor Version 19 | // Build Number 20 | // Revision 21 | // 22 | // You can specify all the values or you can default the Build and Revision Numbers 23 | // by using the '*' as shown below: 24 | // [assembly: AssemblyVersion("1.0.*")] 25 | -------------------------------------------------------------------------------- /AppxActivate/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "AppxActivate": { 4 | "commandName": "Project", 5 | "commandLineArgs": "TEST" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /Dataviewer/AboutBox.designer.vb: -------------------------------------------------------------------------------- 1 | _ 2 | Partial Class AboutBox 3 | Inherits System.Windows.Forms.Form 4 | 5 | 'Form overrides dispose to clean up the component list. 6 | _ 7 | Protected Overrides Sub Dispose(disposing As Boolean) 8 | Try 9 | If disposing AndAlso components IsNot Nothing Then 10 | components.Dispose() 11 | End If 12 | Finally 13 | MyBase.Dispose(disposing) 14 | End Try 15 | End Sub 16 | 17 | Friend WithEvents TableLayoutPanel As System.Windows.Forms.TableLayoutPanel 18 | Friend WithEvents LogoPictureBox As System.Windows.Forms.PictureBox 19 | Friend WithEvents LabelProductName As System.Windows.Forms.Label 20 | Friend WithEvents LabelVersion As System.Windows.Forms.Label 21 | Friend WithEvents LabelCompanyName As System.Windows.Forms.Label 22 | Friend WithEvents TextBoxDescription As System.Windows.Forms.TextBox 23 | Friend WithEvents OKButton As System.Windows.Forms.Button 24 | Friend WithEvents LabelCopyright As System.Windows.Forms.Label 25 | 26 | 'Required by the Windows Form Designer 27 | Private components As System.ComponentModel.IContainer 28 | 29 | 'NOTE: The following procedure is required by the Windows Form Designer 30 | 'It can be modified using the Windows Form Designer. 31 | 'Do not modify it using the code editor. 32 | _ 33 | Private Sub InitializeComponent() 34 | Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(AboutBox)) 35 | Me.TableLayoutPanel = New System.Windows.Forms.TableLayoutPanel 36 | Me.LogoPictureBox = New System.Windows.Forms.PictureBox 37 | Me.LabelProductName = New System.Windows.Forms.Label 38 | Me.LabelVersion = New System.Windows.Forms.Label 39 | Me.LabelCopyright = New System.Windows.Forms.Label 40 | Me.LabelCompanyName = New System.Windows.Forms.Label 41 | Me.TextBoxDescription = New System.Windows.Forms.TextBox 42 | Me.OKButton = New System.Windows.Forms.Button 43 | Me.LinkLabel = New System.Windows.Forms.LinkLabel 44 | Me.TableLayoutPanel.SuspendLayout() 45 | CType(Me.LogoPictureBox, System.ComponentModel.ISupportInitialize).BeginInit() 46 | Me.SuspendLayout() 47 | ' 48 | 'TableLayoutPanel 49 | ' 50 | Me.TableLayoutPanel.ColumnCount = 2 51 | Me.TableLayoutPanel.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.0!)) 52 | Me.TableLayoutPanel.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 67.0!)) 53 | Me.TableLayoutPanel.Controls.Add(Me.LogoPictureBox, 0, 0) 54 | Me.TableLayoutPanel.Controls.Add(Me.LabelProductName, 1, 0) 55 | Me.TableLayoutPanel.Controls.Add(Me.LabelVersion, 1, 1) 56 | Me.TableLayoutPanel.Controls.Add(Me.LabelCopyright, 1, 2) 57 | Me.TableLayoutPanel.Controls.Add(Me.LabelCompanyName, 1, 3) 58 | Me.TableLayoutPanel.Controls.Add(Me.TextBoxDescription, 1, 4) 59 | Me.TableLayoutPanel.Controls.Add(Me.OKButton, 1, 6) 60 | Me.TableLayoutPanel.Controls.Add(Me.LinkLabel, 1, 5) 61 | Me.TableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill 62 | Me.TableLayoutPanel.Location = New System.Drawing.Point(9, 9) 63 | Me.TableLayoutPanel.Name = "TableLayoutPanel" 64 | Me.TableLayoutPanel.RowCount = 7 65 | Me.TableLayoutPanel.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10.0!)) 66 | Me.TableLayoutPanel.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10.0!)) 67 | Me.TableLayoutPanel.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10.0!)) 68 | Me.TableLayoutPanel.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10.0!)) 69 | Me.TableLayoutPanel.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) 70 | Me.TableLayoutPanel.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) 71 | Me.TableLayoutPanel.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10.0!)) 72 | Me.TableLayoutPanel.Size = New System.Drawing.Size(396, 258) 73 | Me.TableLayoutPanel.TabIndex = 0 74 | ' 75 | 'LogoPictureBox 76 | ' 77 | Me.LogoPictureBox.Dock = System.Windows.Forms.DockStyle.Fill 78 | Me.LogoPictureBox.Image = CType(resources.GetObject("LogoPictureBox.Image"), System.Drawing.Image) 79 | Me.LogoPictureBox.Location = New System.Drawing.Point(3, 3) 80 | Me.LogoPictureBox.Name = "LogoPictureBox" 81 | Me.TableLayoutPanel.SetRowSpan(Me.LogoPictureBox, 7) 82 | Me.LogoPictureBox.Size = New System.Drawing.Size(124, 252) 83 | Me.LogoPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage 84 | Me.LogoPictureBox.TabIndex = 0 85 | Me.LogoPictureBox.TabStop = False 86 | ' 87 | 'LabelProductName 88 | ' 89 | Me.LabelProductName.Dock = System.Windows.Forms.DockStyle.Fill 90 | Me.LabelProductName.Location = New System.Drawing.Point(136, 0) 91 | Me.LabelProductName.Margin = New System.Windows.Forms.Padding(6, 0, 3, 0) 92 | Me.LabelProductName.MaximumSize = New System.Drawing.Size(0, 17) 93 | Me.LabelProductName.Name = "LabelProductName" 94 | Me.LabelProductName.Size = New System.Drawing.Size(257, 17) 95 | Me.LabelProductName.TabIndex = 0 96 | Me.LabelProductName.Text = "Product Name" 97 | Me.LabelProductName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft 98 | ' 99 | 'LabelVersion 100 | ' 101 | Me.LabelVersion.Dock = System.Windows.Forms.DockStyle.Fill 102 | Me.LabelVersion.Location = New System.Drawing.Point(136, 23) 103 | Me.LabelVersion.Margin = New System.Windows.Forms.Padding(6, 0, 3, 0) 104 | Me.LabelVersion.MaximumSize = New System.Drawing.Size(0, 17) 105 | Me.LabelVersion.Name = "LabelVersion" 106 | Me.LabelVersion.Size = New System.Drawing.Size(257, 17) 107 | Me.LabelVersion.TabIndex = 0 108 | Me.LabelVersion.Text = "Version" 109 | Me.LabelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft 110 | ' 111 | 'LabelCopyright 112 | ' 113 | Me.LabelCopyright.Dock = System.Windows.Forms.DockStyle.Fill 114 | Me.LabelCopyright.Location = New System.Drawing.Point(136, 46) 115 | Me.LabelCopyright.Margin = New System.Windows.Forms.Padding(6, 0, 3, 0) 116 | Me.LabelCopyright.MaximumSize = New System.Drawing.Size(0, 17) 117 | Me.LabelCopyright.Name = "LabelCopyright" 118 | Me.LabelCopyright.Size = New System.Drawing.Size(257, 17) 119 | Me.LabelCopyright.TabIndex = 0 120 | Me.LabelCopyright.Text = "Copyright" 121 | Me.LabelCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleLeft 122 | ' 123 | 'LabelCompanyName 124 | ' 125 | Me.LabelCompanyName.Dock = System.Windows.Forms.DockStyle.Fill 126 | Me.LabelCompanyName.Location = New System.Drawing.Point(136, 69) 127 | Me.LabelCompanyName.Margin = New System.Windows.Forms.Padding(6, 0, 3, 0) 128 | Me.LabelCompanyName.MaximumSize = New System.Drawing.Size(0, 17) 129 | Me.LabelCompanyName.Name = "LabelCompanyName" 130 | Me.LabelCompanyName.Size = New System.Drawing.Size(257, 17) 131 | Me.LabelCompanyName.TabIndex = 0 132 | Me.LabelCompanyName.Text = "Company Name" 133 | Me.LabelCompanyName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft 134 | ' 135 | 'TextBoxDescription 136 | ' 137 | Me.TextBoxDescription.Dock = System.Windows.Forms.DockStyle.Fill 138 | Me.TextBoxDescription.Location = New System.Drawing.Point(136, 95) 139 | Me.TextBoxDescription.Margin = New System.Windows.Forms.Padding(6, 3, 3, 3) 140 | Me.TextBoxDescription.Multiline = True 141 | Me.TextBoxDescription.Name = "TextBoxDescription" 142 | Me.TextBoxDescription.ReadOnly = True 143 | Me.TextBoxDescription.ScrollBars = System.Windows.Forms.ScrollBars.Both 144 | Me.TextBoxDescription.Size = New System.Drawing.Size(257, 113) 145 | Me.TextBoxDescription.TabIndex = 0 146 | Me.TextBoxDescription.TabStop = False 147 | Me.TextBoxDescription.Text = resources.GetString("TextBoxDescription.Text") 148 | ' 149 | 'OKButton 150 | ' 151 | Me.OKButton.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) 152 | Me.OKButton.DialogResult = System.Windows.Forms.DialogResult.OK 153 | Me.OKButton.Location = New System.Drawing.Point(318, 234) 154 | Me.OKButton.Name = "OKButton" 155 | Me.OKButton.Size = New System.Drawing.Size(75, 21) 156 | Me.OKButton.TabIndex = 0 157 | Me.OKButton.Text = "OK" 158 | ' 159 | 'LinkLabel 160 | ' 161 | Me.LinkLabel.Anchor = System.Windows.Forms.AnchorStyles.Left 162 | Me.LinkLabel.AutoSize = True 163 | Me.LinkLabel.Location = New System.Drawing.Point(133, 214) 164 | Me.LinkLabel.Name = "LinkLabel" 165 | Me.LinkLabel.Size = New System.Drawing.Size(111, 13) 166 | Me.LinkLabel.TabIndex = 1 167 | Me.LinkLabel.TabStop = True 168 | Me.LinkLabel.Text = "http://www.ltr-data.se" 169 | ' 170 | 'AboutBox 171 | ' 172 | Me.AcceptButton = Me.OKButton 173 | Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) 174 | Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font 175 | Me.CancelButton = Me.OKButton 176 | Me.ClientSize = New System.Drawing.Size(414, 276) 177 | Me.Controls.Add(Me.TableLayoutPanel) 178 | Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog 179 | Me.MaximizeBox = False 180 | Me.MinimizeBox = False 181 | Me.Name = "AboutBox" 182 | Me.Padding = New System.Windows.Forms.Padding(9) 183 | Me.ShowInTaskbar = False 184 | Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent 185 | Me.Text = "About" 186 | Me.TableLayoutPanel.ResumeLayout(False) 187 | Me.TableLayoutPanel.PerformLayout() 188 | CType(Me.LogoPictureBox, System.ComponentModel.ISupportInitialize).EndInit() 189 | Me.ResumeLayout(False) 190 | 191 | End Sub 192 | Friend WithEvents LinkLabel As System.Windows.Forms.LinkLabel 193 | 194 | End Class 195 | -------------------------------------------------------------------------------- /Dataviewer/AboutBox.vb: -------------------------------------------------------------------------------- 1 | Imports System.Reflection 2 | Imports System.Text 3 | 4 | Public NotInheritable Class AboutBox 5 | 6 | Protected Overrides Sub OnLoad(e As EventArgs) 7 | MyBase.OnLoad(e) 8 | 9 | Dim asm = Assembly.GetExecutingAssembly() 10 | Dim productName = CType(asm.GetCustomAttributes(GetType(AssemblyProductAttribute), False)(0), AssemblyProductAttribute).Product 11 | Dim title = CType(asm.GetCustomAttributes(GetType(AssemblyTitleAttribute), False)(0), AssemblyTitleAttribute).Title 12 | Dim fileVersion = CType(asm.GetCustomAttributes(GetType(AssemblyFileVersionAttribute), False)(0), AssemblyFileVersionAttribute).Version 13 | Dim legalCopyright = CType(asm.GetCustomAttributes(GetType(AssemblyCopyrightAttribute), False)(0), AssemblyCopyrightAttribute).Copyright 14 | Dim fileDescription = CType(asm.GetCustomAttributes(GetType(AssemblyDescriptionAttribute), False)(0), AssemblyDescriptionAttribute).Description 15 | 16 | ' Set the title of the form. 17 | Dim ApplicationTitle As String 18 | 19 | If title <> "" Then 20 | ApplicationTitle = title 21 | Else 22 | ApplicationTitle = IO.Path.GetFileNameWithoutExtension(asm.Location) 23 | End If 24 | 25 | Text = $"About {ApplicationTitle}" 26 | ' Initialize all of the text displayed on the About Box. 27 | ' TODO: Customize the application's assembly information in the "Application" pane of the project 28 | ' properties dialog (under the "Project" menu). 29 | LabelProductName.Text = productName 30 | LabelVersion.Text = $"Version {fileVersion}" 31 | LabelCopyright.Text = legalCopyright 32 | LabelCompanyName.Text = CompanyName 33 | 34 | Dim sb = New StringBuilder(). 35 | AppendLine(fileDescription). 36 | AppendLine(). 37 | Append("Runtime version "). 38 | AppendLine(Environment.Version.ToString()). 39 | AppendLine(). 40 | Append("OS version "). 41 | AppendLine(Environment.OSVersion.ToString()) 42 | 43 | TextBoxDescription.Text = sb.ToString() 44 | End Sub 45 | 46 | Private Sub OKButton_Click(sender As Object, e As EventArgs) Handles OKButton.Click 47 | Close() 48 | End Sub 49 | 50 | Private Sub LinkLabel_LinkClicked(sender As Object, e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles LinkLabel.LinkClicked 51 | Process.Start(New ProcessStartInfo With {.FileName = "http://www.ltr-data.se", .UseShellExecute = True})?.Dispose() 52 | End Sub 53 | End Class 54 | -------------------------------------------------------------------------------- /Dataviewer/Dataviewer.Designer.vb: -------------------------------------------------------------------------------- 1 | 2 | Partial Class Dataviewer 3 | Inherits System.Windows.Forms.Form 4 | 5 | 'Form overrides dispose to clean up the component list. 6 | 7 | Protected Overrides Sub Dispose(disposing As Boolean) 8 | Try 9 | If disposing AndAlso components IsNot Nothing Then 10 | components.Dispose() 11 | End If 12 | Finally 13 | MyBase.Dispose(disposing) 14 | End Try 15 | End Sub 16 | 17 | 'Required by the Windows Form Designer 18 | Private components As System.ComponentModel.IContainer 19 | 20 | 'NOTE: The following procedure is required by the Windows Form Designer 21 | 'It can be modified using the Windows Form Designer. 22 | 'Do not modify it using the code editor. 23 | 24 | Private Sub InitializeComponent() 25 | Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(Dataviewer)) 26 | Me.Panel1 = New System.Windows.Forms.Panel() 27 | Me.btnDisconnect = New System.Windows.Forms.Button() 28 | Me.btnBrowseDataSources = New System.Windows.Forms.Button() 29 | Me.tbTable = New System.Windows.Forms.TextBox() 30 | Me.Label2 = New System.Windows.Forms.Label() 31 | Me.tbDatasource = New System.Windows.Forms.TextBox() 32 | Me.Label1 = New System.Windows.Forms.Label() 33 | Me.btnAbout = New System.Windows.Forms.Button() 34 | Me.btnLoad = New System.Windows.Forms.Button() 35 | Me.DataGridView = New System.Windows.Forms.DataGridView() 36 | Me.Panel1.SuspendLayout() 37 | CType(Me.DataGridView, System.ComponentModel.ISupportInitialize).BeginInit() 38 | Me.SuspendLayout() 39 | ' 40 | 'Panel1 41 | ' 42 | Me.Panel1.Controls.Add(Me.btnDisconnect) 43 | Me.Panel1.Controls.Add(Me.btnBrowseDataSources) 44 | Me.Panel1.Controls.Add(Me.tbTable) 45 | Me.Panel1.Controls.Add(Me.Label2) 46 | Me.Panel1.Controls.Add(Me.tbDatasource) 47 | Me.Panel1.Controls.Add(Me.Label1) 48 | Me.Panel1.Controls.Add(Me.btnAbout) 49 | Me.Panel1.Controls.Add(Me.btnLoad) 50 | Me.Panel1.Dock = System.Windows.Forms.DockStyle.Top 51 | Me.Panel1.Location = New System.Drawing.Point(0, 0) 52 | Me.Panel1.Name = "Panel1" 53 | Me.Panel1.Size = New System.Drawing.Size(540, 56) 54 | Me.Panel1.TabIndex = 6 55 | ' 56 | 'btnDisconnect 57 | ' 58 | Me.btnDisconnect.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) 59 | Me.btnDisconnect.Enabled = False 60 | Me.btnDisconnect.Location = New System.Drawing.Point(456, 30) 61 | Me.btnDisconnect.Name = "btnDisconnect" 62 | Me.btnDisconnect.Size = New System.Drawing.Size(80, 20) 63 | Me.btnDisconnect.TabIndex = 5 64 | Me.btnDisconnect.Text = "Disconnect" 65 | Me.btnDisconnect.UseVisualStyleBackColor = True 66 | ' 67 | 'btnBrowseDataSources 68 | ' 69 | Me.btnBrowseDataSources.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) 70 | Me.btnBrowseDataSources.Location = New System.Drawing.Point(370, 4) 71 | Me.btnBrowseDataSources.Name = "btnBrowseDataSources" 72 | Me.btnBrowseDataSources.Size = New System.Drawing.Size(80, 20) 73 | Me.btnBrowseDataSources.TabIndex = 2 74 | Me.btnBrowseDataSources.Text = "Data sources" 75 | Me.btnBrowseDataSources.UseVisualStyleBackColor = True 76 | ' 77 | 'tbTable 78 | ' 79 | Me.tbTable.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _ 80 | Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) 81 | Me.tbTable.DataBindings.Add(New System.Windows.Forms.Binding("Text", Global.LTR.DataViewer.My_Project.MySettings.Default, "Table", True, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)) 82 | Me.tbTable.Location = New System.Drawing.Point(74, 30) 83 | Me.tbTable.Name = "tbTable" 84 | Me.tbTable.Size = New System.Drawing.Size(290, 20) 85 | Me.tbTable.TabIndex = 1 86 | Me.tbTable.Text = Global.LTR.DataViewer.My_Project.MySettings.Default.Table 87 | ' 88 | 'Label2 89 | ' 90 | Me.Label2.AutoSize = True 91 | Me.Label2.Location = New System.Drawing.Point(3, 33) 92 | Me.Label2.Name = "Label2" 93 | Me.Label2.Size = New System.Drawing.Size(57, 13) 94 | Me.Label2.TabIndex = 14 95 | Me.Label2.Text = "SQL query" 96 | ' 97 | 'tbDatasource 98 | ' 99 | Me.tbDatasource.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _ 100 | Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) 101 | Me.tbDatasource.DataBindings.Add(New System.Windows.Forms.Binding("Text", Global.LTR.DataViewer.My_Project.MySettings.Default, "Datasource", True, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)) 102 | Me.tbDatasource.Location = New System.Drawing.Point(74, 4) 103 | Me.tbDatasource.Name = "tbDatasource" 104 | Me.tbDatasource.Size = New System.Drawing.Size(290, 20) 105 | Me.tbDatasource.TabIndex = 0 106 | Me.tbDatasource.Text = Global.LTR.DataViewer.My_Project.MySettings.Default.Datasource 107 | ' 108 | 'Label1 109 | ' 110 | Me.Label1.AutoSize = True 111 | Me.Label1.Location = New System.Drawing.Point(3, 7) 112 | Me.Label1.Name = "Label1" 113 | Me.Label1.Size = New System.Drawing.Size(61, 13) 114 | Me.Label1.TabIndex = 13 115 | Me.Label1.Text = "Connection" 116 | ' 117 | 'btnAbout 118 | ' 119 | Me.btnAbout.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) 120 | Me.btnAbout.Location = New System.Drawing.Point(456, 4) 121 | Me.btnAbout.Name = "btnAbout" 122 | Me.btnAbout.Size = New System.Drawing.Size(81, 20) 123 | Me.btnAbout.TabIndex = 4 124 | Me.btnAbout.Text = "About..." 125 | Me.btnAbout.UseVisualStyleBackColor = True 126 | ' 127 | 'btnLoad 128 | ' 129 | Me.btnLoad.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) 130 | Me.btnLoad.Location = New System.Drawing.Point(369, 30) 131 | Me.btnLoad.Name = "btnLoad" 132 | Me.btnLoad.Size = New System.Drawing.Size(81, 20) 133 | Me.btnLoad.TabIndex = 3 134 | Me.btnLoad.Text = "Execute" 135 | Me.btnLoad.UseVisualStyleBackColor = True 136 | ' 137 | 'DataGridView 138 | ' 139 | Me.DataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize 140 | Me.DataGridView.Dock = System.Windows.Forms.DockStyle.Fill 141 | Me.DataGridView.Location = New System.Drawing.Point(0, 56) 142 | Me.DataGridView.Name = "DataGridView" 143 | Me.DataGridView.Size = New System.Drawing.Size(540, 548) 144 | Me.DataGridView.TabIndex = 0 145 | ' 146 | 'Dataviewer 147 | ' 148 | Me.AcceptButton = Me.btnLoad 149 | Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) 150 | Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font 151 | Me.ClientSize = Global.LTR.DataViewer.My_Project.MySettings.Default.Size 152 | Me.Controls.Add(Me.DataGridView) 153 | Me.Controls.Add(Me.Panel1) 154 | Me.DataBindings.Add(New System.Windows.Forms.Binding("Location", Global.LTR.DataViewer.My_Project.MySettings.Default, "WindowLocation", True, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)) 155 | Me.DataBindings.Add(New System.Windows.Forms.Binding("ClientSize", Global.LTR.DataViewer.My_Project.MySettings.Default, "Size", True, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)) 156 | Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon) 157 | Me.Location = Global.LTR.DataViewer.My_Project.MySettings.Default.WindowLocation 158 | Me.Name = "Dataviewer" 159 | Me.Text = "ODBC Dataviewer" 160 | Me.Panel1.ResumeLayout(False) 161 | Me.Panel1.PerformLayout() 162 | CType(Me.DataGridView, System.ComponentModel.ISupportInitialize).EndInit() 163 | Me.ResumeLayout(False) 164 | 165 | End Sub 166 | Friend WithEvents Panel1 As System.Windows.Forms.Panel 167 | Friend WithEvents tbTable As System.Windows.Forms.TextBox 168 | Friend WithEvents Label2 As System.Windows.Forms.Label 169 | Friend WithEvents tbDatasource As System.Windows.Forms.TextBox 170 | Friend WithEvents Label1 As System.Windows.Forms.Label 171 | Friend WithEvents btnLoad As System.Windows.Forms.Button 172 | Friend WithEvents DataGridView As System.Windows.Forms.DataGridView 173 | Friend WithEvents btnAbout As System.Windows.Forms.Button 174 | Friend WithEvents btnBrowseDataSources As System.Windows.Forms.Button 175 | Friend WithEvents btnDisconnect As System.Windows.Forms.Button 176 | 177 | End Class 178 | -------------------------------------------------------------------------------- /Dataviewer/Dataviewer.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LTRData/SystemTools/d7136ccf6b9ab87aa125cabf56a28ee4378bc5d1/Dataviewer/Dataviewer.ico -------------------------------------------------------------------------------- /Dataviewer/Dataviewer.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | 123 | AAABAAQAEBAAAAEACABoBQAARgAAABAQAAABACAAaAQAAK4FAAAgIAAAAQAIAKgIAAAWCgAAICAAAAEA 124 | IACoEAAAvhIAACgAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAmTMAAMtV 125 | GQDLZgAA3m42AOJ3QgDziVQAGW+cACRznQAfe6sAJHagACmEswA8i7QARZCvAHmpugAEk84AAJbVABGp 126 | 4gAkue4AJr/2AEqfwgBMoMEAVKvMAE/R+wBh3P0AiaaxAICwvQCAvM8Ajr3MAJe8yQCxz90AjuDwAJ7t 127 | /ACh6/YArvb9ALP8/wDP3OQAxeDoANjn7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 128 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 129 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 130 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 131 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 132 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 133 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 134 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 135 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 136 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 137 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 138 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 139 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 140 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 141 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 142 | AAMBAAAAAAAAAAAAAAAAAAMFAgEAAAAAAAAAAAAAAAMEBgUCAQAAAAAAAAAAAAAAAAQEAAAAAAAAAAAA 143 | AAAAHgwLCQckAAAAAAAAAAEAAA0XIRIPCAAAAQAAAAECAAAUFyESEAgAAAIBAAECBQEBFRchEhAIAQEF 144 | AgEEBQYEAhUXIRIQCAIEBgUDAAQGAAAWGCETEQoAAAQDAAAABAAAGyAiIx8ZAAADAAAAAAAAACUcGg4d 145 | JgAAAAAAAAAAAAAAAAQBAAAAAAAAAAAAAAAABAUGBQEBAAAAAAAAAAAAAAAEBQIDAAAAAAAAAAAAAAAA 146 | AAQDAAAAAAAAAP5/AAD8PwAA+B8AAP5/AAD4HwAA2BsAAJgZAAAAAAAAAAAAAJgZAADYGwAA+B8AAP5/ 147 | AAD4HwAA/D8AAP5/AAAoAAAAEAAAACAAAAABACAAAAAAAEAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 148 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMtmAP+ZMwD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 149 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMtmAP/id0L/y1UZ/5kzAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 150 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMtmAP/ebjb/84lU/+J3Qv/LVRn/mTMA/wAAAAAAAAAAAAAAAAAA 151 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN5uNv/ebjb/AAAAAAAAAAAAAAAAAAAAAAAA 152 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsc/d/zyLtP8phLP/H3ur/xlvnP/P3OT/AAAAAAAA 153 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJkzAP8AAAAAAAAAAEWQr/9P0fv/oev2/yS57v8Ek87/JHOd/wAA 154 | AAAAAAAAmTMA/wAAAAAAAAAAAAAAAJkzAP/LVRn/AAAAAAAAAABKn8L/T9H7/6Hr9v8kue7/AJbV/yRz 155 | nf8AAAAAAAAAAMtVGf+ZMwD/AAAAAJkzAP/LVRn/4ndC/5kzAP+ZMwD/TKDB/0/R+/+h6/b/JLnu/wCW 156 | 1f8kc53/mTMA/5kzAP/id0L/y1UZ/5kzAP/ebjb/4ndC//OJVP/ebjb/y1UZ/0ygwf9P0fv/oev2/yS5 157 | 7v8AltX/JHOd/8tVGf/ebjb/84lU/+J3Qv/LZgD/AAAAAN5uNv/ziVT/AAAAAAAAAABUq8z/Ydz9/6Hr 158 | 9v8mv/b/Eani/yR2oP8AAAAAAAAAAN5uNv/LZgD/AAAAAAAAAAAAAAAA3m42/wAAAAAAAAAAgLzP/57t 159 | /P+u9v3/s/z//47g8P+JprH/AAAAAAAAAADLZgD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMXg 160 | 6P+Ovcz/gLC9/3mpuv+XvMn/2Ofs/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 161 | AAAAAAAAAAAAAN5uNv+ZMwD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 162 | AAAAAAAA3m42/+J3Qv/ziVT/4ndC/5kzAP+ZMwD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 163 | AAAAAAAAAAAAAAAAAADebjb/4ndC/8tVGf/LZgD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 164 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN5uNv/LZgD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP5/ 165 | AAD8PwAA+B8AAP5/AAD4HwAA2BsAAJgZAAAAAAAAAAAAAJgZAADYGwAA+B8AAP5/AAD4HwAA/D8AAP5/ 166 | AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAEAAAAAAAAAAAAAAABAAAAAQAAPV56AD5ffABAYn4AnjUEAKNV 167 | OgDRahYAy2M1AOp/UADxiEUA6YZRAPCOWAD/oG0ANW6QAEJlgABEaIMARmuGAEVshwBJbogASnCKAE50 168 | jgBBc5IAUHeQAFN6kwBVfZUAIoCsAFuDmgBahJsAXYeeAEWBogBfiaAAVI+rAGGMogBkj6UAZZKoAGiV 169 | qwBqmK0AbZquAG2bsABkm7oAbZ+6AHCfsgBco78AcaG1AHSjuAB5p7oAe6i4ABaSxwAJltIAA5vaAASb 170 | 2wADnNoABJzaACSq3QABoeEAAqfoAAKo6AAete0APrjlAES95wB4wNQAQ8TvAFDG7ABDxPAARcXwAFDK 171 | 8ABn0/EAatDwAGnU8QBr1fQAgqu9AIa0xwCEuM8AjLnIAIy9zACUt8UAm7/MAJTE0QCdz9sApczYAKjK 172 | 2wCV2eYAgdvwAILf8wCC3/QAqdrjAK3f6AC31+QAjOL0AJro9wCi6/YAuOvxALns8wCv8PsAtfP6APXf 173 | zgD86dwAwdngAMnj6QDC9foAwff9AML4/ADF+f0A8/j5APX6+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 174 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 175 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 176 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 177 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 178 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 179 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 180 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 181 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 182 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 183 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhoaGhoaGhoaGhoaGho 184 | aGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoBQRoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGho 185 | aGhoaAUKBgRoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGgFCgsKBgRoaGhoaGhoaGhoaGhoaGhoaGho 186 | aGhoaGhoBQoLCwoKBgRoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaAUFBQcLCQQEBARoaGhoaGhoaGhoaGho 187 | aGhoaGhoaGhoaGhoBQsJBGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGgFCgkEaGhoaGhoaGhoaGho 188 | aGhoaGhoaGhoaGhoaFZGJBkSEBQcJk9oaGhoaGhoaGhoaGhoaGhoaGhoaGhHHik7UFE9NC4YDCdoaGho 189 | aGhoaGhoaGhoaGhoA2hoaBk6QVdZUUA4NzUvAGhoaARoaGhoaGhoaGhoaAMDaGhoGT9DV1lTQDg3NTIA 190 | aGhoBARoaGhoaGhoaGgDBgpoaGgdP0FXWVFAODc1MgJoaGgEBgRoaGhoaGhoAwYICAMDAx0/Q1dZU0A4 191 | NzUyDQQEBAYJBgRoaGhoaAMGCAoKCgoKID9DV1lRQDg3NTIQCQkJCQkJBgRoaGhoBgoLCwsLCwohP0NX 192 | WVNAODc1MhAJCwsLCwsJBmhoaGhoBgoLCgUFBSI/Q1dZU0A4NzUyEQYGBgkLCQZoaGhoaGhoBgoFaGho 193 | JD9DV1lTQDg3NTISaGhoBgkGaGhoaGhoaGhoBgVoaGglP0NXWVNAODc1MhJoaGgGBmhoaGhoaGhoaGho 194 | BWhoaCg/Q1dZU0A4NzUyFWhoaAZoaGhoaGhoaGhoaGhoaGhoKkNYXWVlZVxXQzkVaGhoaGhoaGhoaGho 195 | aGhoaGhoaGgrZWVlZWVlZWVlZRVoaGhoaGhoaGhoaGhoaGhoaGhoaE5JTVVbYmJbVEwtSmhoaGhoaGho 196 | aGhoaGhoaGhoaGhoZ2FOSSwkJChFS2BnaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoBQgGA2hoaGhoaGho 197 | aGhoaGhoaGhoaGhoaGhoaGhoaGgFCwYDaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaAUFBQcLBwYDAwNo 198 | aGhoaGhoaGhoaGhoaGhoaGhoaGhoaAUKCwsICAYDaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaAUKCwgG 199 | A2hoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaAUKBgNoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGho 200 | aAUDaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGj///////5////8 201 | P///+B////AP///gB////D////w////gB///wAP//cADv/nAA5/xwAOP4AAAB8AAAAPAAAAD4AAAB/HA 202 | A4/5wAOf/cADv//AA///wAP//8AD///AA////D////w////gB///8A////gf///8P////n///////ygA 203 | AAAgAAAAQAAAAAEAIAAAAAAAgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 204 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 205 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 206 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANFqFv+jVTr/AAAAAAAA 207 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 208 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADRahb/8I5Y/8tj 209 | Nf+jVTr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 210 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0WoW//CO 211 | WP//oG3/8I5Y/8tjNf+jVTr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 212 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANFq 213 | Fv/wjlj//6Bt//+gbf/wjlj/8I5Y/8tjNf+jVTr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 214 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 215 | AADRahb/0WoW/9FqFv/qf1D//6Bt/+mGUf+jVTr/o1U6/6NVOv+jVTr/AAAAAAAAAAAAAAAAAAAAAAAA 216 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 217 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAANFqFv//oG3/6YZR/6NVOv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 218 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 219 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0WoW//COWP/phlH/o1U6/wAAAAAAAAAAAAAAAAAA 220 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 221 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC31+T/hrTH/22arv9bg5r/SnCK/0Vsh/9Bc5L/RYGi/2Sb 222 | uv+oytv/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 223 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhLjP/1SPq/9co7//eMDU/5XZ5v+B2/D/UMbs/ySq 224 | 3f8Wksf/IoCs/zVukP9tn7r/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 225 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ41BP8AAAAAAAAAAAAAAABbg5r/RL3n/2fT8f+M4vT/ouv2/4Hb 226 | 8P9QyvD/HrXt/wKo6P8BoeH/CZbS/z1eev8AAAAAAAAAAAAAAACjVTr/AAAAAAAAAAAAAAAAAAAAAAAA 227 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACeNQT/njUE/wAAAAAAAAAAAAAAAFuDmv9FxfD/adTx/4zi 228 | 9P+i6/b/gt/0/1DK8P8ete3/Aqjo/wGh4f8DnNr/PV56/wAAAAAAAAAAAAAAAKNVOv+jVTr/AAAAAAAA 229 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnjUE/8tjNf/wjlj/AAAAAAAAAAAAAAAAX4mg/0XF 230 | 8P9n0/H/jOL0/6Lr9v+B2/D/UMrw/x617f8CqOj/AaHh/wOc2v9AYn7/AAAAAAAAAAAAAAAAo1U6/8tj 231 | Nf+jVTr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ41BP/LYzX/8YhF//GIRf+eNQT/njUE/541 232 | BP9fiaD/RcXw/2nU8f+M4vT/ouv2/4Lf9P9QyvD/HrXt/wKo6P8BoeH/A5za/0JlgP+jVTr/o1U6/6NV 233 | Ov/LYzX/6YZR/8tjNf+jVTr/AAAAAAAAAAAAAAAAAAAAAAAAAACeNQT/y2M1//GIRf/wjlj/8I5Y//CO 234 | WP/wjlj/8I5Y/2SPpf9FxfD/adTx/4zi9P+i6/b/gdvw/1DK8P8ete3/Aqjo/wGh4f8DnNr/RWyH/+mG 235 | Uf/phlH/6YZR/+mGUf/phlH/6YZR/8tjNf+jVTr/AAAAAAAAAAAAAAAAAAAAAMtjNf/wjlj//6Bt//+g 236 | bf//oG3//6Bt//+gbf/wjlj/ZZKo/0XF8P9p1PH/jOL0/6Lr9v+C3/T/UMrw/x617f8CqOj/AaHh/wOc 237 | 2v9FbIf/6YZR//+gbf//oG3//6Bt//+gbf//oG3/6YZR/8tjNf8AAAAAAAAAAAAAAAAAAAAAAAAAAMtj 238 | Nf/wjlj//6Bt//COWP/Rahb/0WoW/9FqFv9olav/RcXw/2nU8f+M4vT/ouv2/4Lf9P9QyvD/HrXt/wKo 239 | 6P8BoeH/A5za/0luiP/LYzX/y2M1/8tjNf/phlH//6Bt/+mGUf/LYzX/AAAAAAAAAAAAAAAAAAAAAAAA 240 | AAAAAAAAAAAAAMtjNf/wjlj/0WoW/wAAAAAAAAAAAAAAAG2arv9FxfD/adTx/4zi9P+i6/b/gt/0/1DK 241 | 8P8ete3/Aqjo/wGh4f8DnNr/SnCK/wAAAAAAAAAAAAAAAMtjNf/phlH/y2M1/wAAAAAAAAAAAAAAAAAA 242 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMtjNf/Rahb/AAAAAAAAAAAAAAAAbZuw/0XF8P9p1PH/jOL0/6Lr 243 | 9v+C3/T/UMrw/x617f8CqOj/AaHh/wOc2v9KcIr/AAAAAAAAAAAAAAAAy2M1/8tjNf8AAAAAAAAAAAAA 244 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANFqFv8AAAAAAAAAAAAAAABwn7L/RcXw/2nU 245 | 8f+M4vT/ouv2/4Lf9P9QyvD/HrXt/wKo6P8BoeH/A5za/1B3kP8AAAAAAAAAAAAAAADLYzX/AAAAAAAA 246 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHGh 247 | tf9p1PH/muj3/7Xz+v/F+f3/xfn9/8X5/f+v8Pv/jOL0/2nU8f8+uOX/UHeQ/wAAAAAAAAAAAAAAAAAA 248 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 249 | AAAAAAAAdKO4/8X5/f/F+f3/xfn9/8X5/f/F+f3/xfn9/8X5/f/F+f3/xfn9/8X5/f9Qd5D/AAAAAAAA 250 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 251 | AAAAAAAAAAAAAAAAAAClzNj/jL3M/53P2/+t3+j/uezz/8L1+v/C9fr/uezz/6na4/+UxNH/e6i4/5S3 252 | xf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 253 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX6+//J4+n/pczY/4y9zP95p7r/bZqu/22arv9wn7L/gqu9/5u/ 254 | zP/B2eD/9fr7/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 255 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANFqFv/xiEX/y2M1/541 256 | BP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 257 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0WoW//+g 258 | bf/LYzX/njUE/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 259 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADRahb/0WoW/9Fq 260 | Fv/qf1D//6Bt/+p/UP/LYzX/njUE/541BP+eNQT/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 261 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 262 | AADRahb/8I5Y//+gbf//oG3/8YhF//GIRf/LYzX/njUE/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 263 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 264 | AAAAAAAAAAAAAAAAAADRahb/8I5Y//+gbf/xiEX/y2M1/541BP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 265 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 266 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADRahb/8I5Y/8tjNf+eNQT/AAAAAAAAAAAAAAAAAAAAAAAA 267 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 268 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADRahb/njUE/wAAAAAAAAAAAAAAAAAA 269 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 270 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 271 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///////+ 272 | f////D////gf///wD///4Af///w////8P///4Af//8AD//3AA7/5wAOf8cADj+AAAAfAAAADwAAAA+AA 273 | AAfxwAOP+cADn/3AA7//wAP//8AD///AA///wAP///w////8P///4Af///AP///4H////D////5///// 274 | //8= 275 | 276 | 277 | -------------------------------------------------------------------------------- /Dataviewer/Dataviewer.vb: -------------------------------------------------------------------------------- 1 | Imports System.ComponentModel 2 | Imports System.Data 3 | Imports System.Threading 4 | Imports System.Windows.Forms 5 | Imports Microsoft.Win32 6 | 7 | #Disable Warning IDE1006 ' Naming Styles 8 | 9 | Partial Public Class Dataviewer 10 | 11 | Private Declare Function SQLManageDataSources Lib "ODBCCP32.dll" (hwnd As IntPtr) As Boolean 12 | 13 | Private BindingManager As BindingManagerBase 14 | Private DataAdapter As Odbc.OdbcDataAdapter 15 | Private WithEvents SourceTable As DataTable 16 | 17 | Public Sub SetSourceTable(DataTable As DataTable) 18 | If SourceTable IsNot Nothing Then 19 | SourceTable.Dispose() 20 | End If 21 | SourceTable = Nothing 22 | DataGridView.DataSource = DataTable 23 | SourceTable = DataTable 24 | DataGridView.ReadOnly = False 25 | btnDisconnect.Enabled = DataTable IsNot Nothing 26 | End Sub 27 | 28 | Private Sub DataTable_RowChanged(sender As Object, e As EventArgs) _ 29 | Handles _ 30 | SourceTable.RowChanged, 31 | SourceTable.RowDeleted, 32 | SourceTable.TableNewRow 33 | 34 | Try 35 | DataAdapter.Update(SourceTable) 36 | 37 | Catch ex As Exception 38 | Dim message = ex.GetBaseException().Message 39 | MessageBox.Show(Me, message, "Error updating data source", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) 40 | 41 | End Try 42 | 43 | End Sub 44 | 45 | Protected Overrides Sub OnLoad(e As EventArgs) 46 | MyBase.OnLoad(e) 47 | 48 | tbDatasource.Text = Registry.GetValue("HKEY_CURRENT_USER\Software\LTR Data\DataViewer", "DataSource", Nothing)?.ToString() 49 | tbTable.Text = Registry.GetValue("HKEY_CURRENT_USER\Software\LTR Data\DataViewer", "Query", Nothing)?.ToString() 50 | End Sub 51 | 52 | Protected Overrides Sub OnShown(e As EventArgs) 53 | MyBase.OnShown(e) 54 | 55 | tbTable.Select() 56 | End Sub 57 | 58 | Protected Overrides Sub OnClosing(e As CancelEventArgs) 59 | MyBase.OnClosing(e) 60 | 61 | If BindingManager IsNot Nothing Then 62 | BindingManager.EndCurrentEdit() 63 | End If 64 | 65 | Registry.SetValue("HKEY_CURRENT_USER\Software\LTR Data\DataViewer", "DataSource", tbDatasource.Text) 66 | Registry.SetValue("HKEY_CURRENT_USER\Software\LTR Data\DataViewer", "Query", tbTable.Text) 67 | End Sub 68 | 69 | Private Sub btnLoad_Click(sender As Object, e As EventArgs) Handles btnLoad.Click 70 | 71 | Enabled = False 72 | 73 | If BindingManager IsNot Nothing Then 74 | BindingManager.EndCurrentEdit() 75 | BindingManager = Nothing 76 | End If 77 | 78 | SetSourceTable(Nothing) 79 | 80 | If DataAdapter IsNot Nothing Then 81 | DataAdapter.SelectCommand.Connection.Dispose() 82 | DataAdapter.Dispose() 83 | DataAdapter = Nothing 84 | End If 85 | 86 | Dim ConnectionString = tbDatasource.Text 87 | Dim CommandString = tbTable.Text 88 | 89 | ThreadPool.QueueUserWorkItem( 90 | Sub() 91 | 92 | Dim Connection As New Odbc.OdbcConnection 93 | Dim NewSourceTable As New DataTable 94 | Try 95 | Connection.ConnectionString = ConnectionString 96 | Connection.ConnectionTimeout = 20 97 | Connection.Open() 98 | 99 | Dim Command As New Odbc.OdbcCommand(CommandString, Connection) With { 100 | .CommandTimeout = 45 101 | } 102 | 103 | DataAdapter = New Odbc.OdbcDataAdapter(Command) 104 | 105 | With New Odbc.OdbcCommandBuilder(DataAdapter) 106 | End With 107 | 108 | DataAdapter.Fill(NewSourceTable) 109 | 110 | If NewSourceTable.Columns.Count = 0 Then 111 | NewSourceTable = Nothing 112 | DataAdapter = Nothing 113 | BindingManager = Nothing 114 | 115 | Connection.Dispose() 116 | 117 | Invoke(Sub() 118 | MessageBox.Show(Me, "Command executed successfully.", Text, MessageBoxButtons.OK, MessageBoxIcon.Information) 119 | Enabled = True 120 | End Sub) 121 | 122 | Exit Sub 123 | End If 124 | 125 | Catch ex As Exception 126 | NewSourceTable = Nothing 127 | DataAdapter = Nothing 128 | BindingManager = Nothing 129 | 130 | Connection.Dispose() 131 | 132 | Dim message = ex.GetBaseException().Message 133 | 134 | Invoke(Sub() 135 | MessageBox.Show(Me, message, "Error connecting to data source", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) 136 | Enabled = True 137 | End Sub) 138 | 139 | Exit Sub 140 | End Try 141 | 142 | With DataGridView 143 | For Each DataGridViewColumn In .Columns 144 | .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells 145 | Next 146 | End With 147 | 148 | BindingManager = BindingContext(NewSourceTable) 149 | 150 | Invoke(Sub() 151 | SetSourceTable(NewSourceTable) 152 | Enabled = True 153 | End Sub) 154 | 155 | End Sub) 156 | 157 | End Sub 158 | 159 | Private Sub TextBox_LostFocus(sender As Object, e As EventArgs) Handles tbDatasource.LostFocus, tbTable.LostFocus 160 | With DirectCast(sender, TextBox) 161 | .SelectionStart = 0 162 | .SelectionLength = .TextLength 163 | End With 164 | End Sub 165 | 166 | Private Sub DataGridView_DataError(sender As Object, e As DataGridViewDataErrorEventArgs) Handles DataGridView.DataError 167 | If TypeOf e.Exception Is FormatException Then 168 | MessageBox.Show(Me, e.Exception.GetBaseException().Message, "Data format error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) 169 | End If 170 | End Sub 171 | 172 | Private Sub btnAbout_Click(sender As Object, e As EventArgs) Handles btnAbout.Click 173 | Using AboutBox As New AboutBox 174 | AboutBox.ShowDialog(Me) 175 | End Using 176 | End Sub 177 | 178 | Private Sub btnBrowseDataSources_Click(sender As Object, e As EventArgs) Handles btnBrowseDataSources.Click 179 | SQLManageDataSources(Handle) 180 | End Sub 181 | 182 | Private Sub btnDisconnect_Click(sender As Object, e As EventArgs) Handles btnDisconnect.Click 183 | Try 184 | DataGridView.ReadOnly = True 185 | 186 | If DataAdapter IsNot Nothing Then 187 | DataAdapter.SelectCommand.Connection.Dispose() 188 | DataAdapter = Nothing 189 | SourceTable.Dispose() 190 | SourceTable = Nothing 191 | End If 192 | 193 | btnDisconnect.Enabled = False 194 | 195 | Catch ex As Exception 196 | MessageBox.Show(Me, ex.GetBaseException().Message, "Error closing data source", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) 197 | 198 | End Try 199 | End Sub 200 | End Class 201 | -------------------------------------------------------------------------------- /Dataviewer/Dataviewer.vbproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | WinExe 6 | net9.0-windows;net8.0-windows;net20;net40 7 | LTR.DataViewer 8 | true 9 | 10 | 11 | 12 | ODBC Dataviewer 13 | Utility to make ODBC connections, send SQL queries and update data. 14 | LTR Data 15 | ODBC Dataviewer 16 | Copyright © Olof Lagerkvist, LTR Data 2007-2022 17 | 1.1.0.0 18 | 1.1.0.0 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Dataviewer/My Project/Settings.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 Global.LTR.DataViewer.My_Project 16 | 17 | 20 | Partial Friend NotInheritable Class MySettings 21 | Inherits Global.System.Configuration.ApplicationSettingsBase 22 | 23 | Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()), MySettings) 24 | 25 | #Region "My.Settings Auto-Save Functionality" 26 | #If _MyType = "WindowsForms" Then 27 | Private Shared addedHandler As Boolean 28 | 29 | Private Shared addedHandlerLockObject As New Object 30 | 31 | _ 32 | Private Shared Sub AutoSaveSettings(sender As Global.System.Object, e As Global.System.EventArgs) 33 | If My.Application.SaveMySettingsOnExit Then 34 | My.Settings.Save() 35 | End If 36 | End Sub 37 | #End If 38 | #End Region 39 | 40 | Public Shared ReadOnly Property [Default]() As MySettings 41 | Get 42 | 43 | #If _MyType = "WindowsForms" Then 44 | If Not addedHandler Then 45 | SyncLock addedHandlerLockObject 46 | If Not addedHandler Then 47 | AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings 48 | addedHandler = True 49 | End If 50 | End SyncLock 51 | End If 52 | #End If 53 | Return defaultInstance 54 | End Get 55 | End Property 56 | 57 | 72 | Public Property Table() As String 73 | Get 74 | Return CType(Me("Table"), String) 75 | End Get 76 | Set 77 | Me("Table") = Value 78 | End Set 79 | End Property 80 | 81 | 84 | Public Property WindowLocation() As Global.System.Drawing.Point 85 | Get 86 | Return CType(Me("WindowLocation"), Global.System.Drawing.Point) 87 | End Get 88 | Set 89 | Me("WindowLocation") = Value 90 | End Set 91 | End Property 92 | 93 | 96 | Public Property Size() As Global.System.Drawing.Size 97 | Get 98 | Return CType(Me("Size"), Global.System.Drawing.Size) 99 | End Get 100 | Set 101 | Me("Size") = Value 102 | End Set 103 | End Property 104 | End Class 105 | End Namespace 106 | 107 | Namespace My 108 | 109 | _ 112 | Friend Module MySettingsProperty 113 | 114 | 115 | Friend ReadOnly Property Settings() As Global.LTR.DataViewer.My_Project.MySettings 116 | Get 117 | Return Global.LTR.DataViewer.My_Project.MySettings.Default 118 | End Get 119 | End Property 120 | End Module 121 | End Namespace 122 | -------------------------------------------------------------------------------- /Dataviewer/My Project/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | DSN= 7 | 8 | 9 | 10 | 11 | 12 | 100, 200 13 | 14 | 15 | 540, 604 16 | 17 | 18 | -------------------------------------------------------------------------------- /Dataviewer/My Project/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 54 | -------------------------------------------------------------------------------- /Dataviewer/Program.vb: -------------------------------------------------------------------------------- 1 | Imports System.Windows.Forms 2 | 3 | Public Module Program 4 | 5 | Public Sub Main() 6 | 7 | Application.EnableVisualStyles() 8 | Application.Run(New Dataviewer) 9 | 10 | End Sub 11 | 12 | End Module 13 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ..\$(Configuration)\ 5 | false 6 | true 7 | ..\$(Configuration)\ 8 | Latest 9 | On 10 | false 11 | LatestMajor 12 | enable 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /DiskVolumes/DiskVolumes.cs: -------------------------------------------------------------------------------- 1 | using LTRLib.IO; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.ComponentModel; 6 | using System.IO; 7 | using LTRData.Extensions.Formatting; 8 | 9 | namespace DiskVolumes; 10 | 11 | public static class DiskVolumes 12 | { 13 | public static int UnsafeMain(params string[] args) 14 | { 15 | var argList = new List(args); 16 | 17 | var showContainedMountPoints = false; 18 | if (argList.RemoveAll(arg => "/S".Equals(arg, StringComparison.OrdinalIgnoreCase)) > 0) 19 | { 20 | showContainedMountPoints = true; 21 | } 22 | 23 | if (argList.Count == 0) 24 | { 25 | ListVolumes(showContainedMountPoints); 26 | } 27 | else 28 | { 29 | argList.ForEach(arg => ListVolume(arg, showContainedMountPoints)); 30 | } 31 | 32 | //if (Debugger.IsAttached) 33 | //{ 34 | // Console.ReadKey(); 35 | //} 36 | 37 | return 0; 38 | } 39 | 40 | public static int ListVolumes(bool showContainedMountPoints) 41 | { 42 | foreach (var vol in new VolumeEnumerator()) 43 | { 44 | Console.WriteLine(vol); 45 | 46 | ListVolume(vol, showContainedMountPoints); 47 | 48 | Console.WriteLine(); 49 | } 50 | 51 | return 0; 52 | } 53 | 54 | public static int ListVolume(string vol, bool showContainedMountPoints) 55 | { 56 | try 57 | { 58 | var target = NativeFileIO.QueryDosDevice(vol.Substring(4, 44))?.FirstOrDefault(); 59 | 60 | Console.WriteLine($"Device object: {target}"); 61 | 62 | var links = NativeFileIO.QueryDosDevice() 63 | .Select(l => new { l, t = NativeFileIO.QueryDosDevice(l) }) 64 | .Where(o => o.t is not null && o.t.Contains(target, StringComparer.OrdinalIgnoreCase)) 65 | .Select(o => o.l); 66 | 67 | Console.WriteLine("Device object links:"); 68 | 69 | foreach (var link in links) 70 | { 71 | Console.WriteLine($" {link}"); 72 | } 73 | 74 | var mnt = NativeFileIO.GetVolumeMountPoints(vol); 75 | 76 | if (mnt.Length == 0) 77 | { 78 | Console.WriteLine("No mountpoints"); 79 | } 80 | else 81 | { 82 | Console.WriteLine($"Mounted at:"); 83 | 84 | foreach (var m in mnt) 85 | { 86 | Console.WriteLine($" {m}"); 87 | } 88 | } 89 | 90 | Console.WriteLine($"Disk extents:"); 91 | 92 | using var volobj = NativeFileIO.OpenFileHandle(vol.TrimEnd('\\'), FileMode.Open, 0, FileShare.ReadWrite, false); 93 | 94 | foreach (var ext in NativeFileIO.GetVolumeDiskExtents(volobj)) 95 | { 96 | Console.WriteLine($" Disk {ext.DiskNumber} at {ext.StartingOffset}, {ext.ExtentLength} bytes ({SizeFormatting.FormatBytes(ext.ExtentLength)})."); 97 | } 98 | } 99 | catch (Exception ex) 100 | { 101 | if (ex is not Win32Exception wex || wex.NativeErrorCode != 1) 102 | { 103 | Console.Error.WriteLine(ex.JoinMessages()); 104 | } 105 | } 106 | 107 | if (showContainedMountPoints) 108 | { 109 | try 110 | { 111 | foreach (var mnt in new VolumeMountPointEnumerator(vol)) 112 | { 113 | var volmnt = vol + mnt; 114 | 115 | Console.Write($"Contains mount point at {mnt}: "); 116 | try 117 | { 118 | var target = NativeFileIO.GetVolumeNameForVolumeMountPoint(volmnt); 119 | Console.Write($"{target}: "); 120 | var target_mounts = NativeFileIO.GetVolumeMountPoints(target).Length; 121 | if (target_mounts == 0) 122 | { 123 | Console.WriteLine("(not attached)"); 124 | } 125 | else 126 | { 127 | Console.WriteLine($"({target_mounts} mount points)"); 128 | } 129 | } 130 | catch (Exception ex) 131 | { 132 | Console.Error.WriteLine($"Error: {ex.JoinMessages()}"); 133 | } 134 | } 135 | } 136 | catch (Exception ex) 137 | { 138 | Console.Error.WriteLine($"Error enumerating contained mount points: {ex.JoinMessages()}"); 139 | } 140 | } 141 | 142 | return 0; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /DiskVolumes/DiskVolumes.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Exe 6 | net8.0;net9.0;net35;net40 7 | DiskVolumes 8 | DiskVolumes 9 | Copyright © LTR Data, Olof Lagerkvist 2015-2022 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /DiskVolumes/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace DiskVolumes; 5 | 6 | public static class Program 7 | { 8 | public static int Main(params string[] args) 9 | { 10 | try 11 | { 12 | return DiskVolumes.UnsafeMain(args); 13 | } 14 | catch (Exception ex) 15 | { 16 | Trace.WriteLine(ex.ToString()); 17 | Console.ForegroundColor = ConsoleColor.Red; 18 | Console.WriteLine(ex.ToString()); 19 | Console.ResetColor(); 20 | return -1; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /DiskVolumes/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using System.Runtime.Versioning; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | 8 | // Setting ComVisible to false makes the types in this assembly not visible 9 | // to COM components. If you need to access a type in this assembly from 10 | // COM, set the ComVisible attribute to true on that type. 11 | [assembly: ComVisible(false)] 12 | 13 | // The following GUID is for the ID of the typelib if this project is exposed to COM 14 | [assembly: Guid("893247e9-fcc6-4407-b85b-f78b05521f27")] 15 | 16 | // Version information for an assembly consists of the following four values: 17 | // 18 | // Major Version 19 | // Minor Version 20 | // Build Number 21 | // Revision 22 | // 23 | // You can specify all the values or you can default the Build and Revision Numbers 24 | // by using the '*' as shown below: 25 | // [assembly: AssemblyVersion("1.0.*")] 26 | 27 | [assembly: SupportedOSPlatform("windows")] 28 | -------------------------------------------------------------------------------- /GetProductKey/GetProductKey.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | LTR.GetProductKey 5 | Exe 6 | net46;net9.0;net8.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /GetProductKey/Program.cs: -------------------------------------------------------------------------------- 1 | using DiscUtils; 2 | using DiscUtils.Iso9660; 3 | using DiscUtils.Streams; 4 | using DiscUtils.Udf; 5 | using DiscUtils.Wim; 6 | using System; 7 | using System.Collections.Concurrent; 8 | using System.Collections.Generic; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | using DiscUtilsRegistryHive = DiscUtils.Registry.RegistryHive; 14 | using DiscUtilsRegistryKey = DiscUtils.Registry.RegistryKey; 15 | using Microsoft.Win32; 16 | using Microsoft.Management.Infrastructure; 17 | using System.Reflection; 18 | 19 | #pragma warning disable IDE0079 // Remove unnecessary suppression 20 | #pragma warning disable CA1416 // Validate platform compatibility 21 | #pragma warning disable IDE0057 // Use range operator 22 | 23 | namespace LTR.GetProductKey; 24 | 25 | public static class Program 26 | { 27 | private static readonly object _syncObj = new(); 28 | 29 | static Program() 30 | { 31 | var asms = new[] 32 | { 33 | typeof(DiscUtils.Fat.FatFileSystem).Assembly, 34 | typeof(DiscUtils.Ntfs.NtfsFileSystem).Assembly, 35 | typeof(DiscUtils.Udf.UdfReader).Assembly, 36 | typeof(DiscUtils.Iso9660.CDReader).Assembly, 37 | typeof(DiscUtils.Wim.WimFileSystem).Assembly, 38 | typeof(DiscUtils.Dmg.Disk).Assembly, 39 | typeof(DiscUtils.Vmdk.Disk).Assembly, 40 | typeof(DiscUtils.Vdi.Disk).Assembly, 41 | typeof(DiscUtils.Vhd.Disk).Assembly, 42 | typeof(DiscUtils.Vhdx.Disk).Assembly 43 | }; 44 | foreach (var asm in asms.Distinct()) 45 | { 46 | try 47 | { 48 | DiscUtils.Setup.SetupHelper.RegisterAssembly(asm); 49 | } 50 | catch (TypeInitializationException ex) when (ex.GetBaseException() is ReflectionTypeLoadException rtle) 51 | { 52 | Console.ForegroundColor = ConsoleColor.Red; 53 | Console.Error.WriteLine($"Failed to load {asm}: {rtle.LoaderExceptions.First()?.GetBaseException().Message}"); 54 | Console.ResetColor(); 55 | } 56 | catch (Exception ex) 57 | { 58 | Console.ForegroundColor = ConsoleColor.Red; 59 | Console.Error.WriteLine($"Failed to load {asm}: {ex.GetType().Name}: {ex.GetBaseException().Message}"); 60 | Console.ResetColor(); 61 | } 62 | } 63 | } 64 | 65 | private static string FormatMessage(this Exception ex) => 66 | #if DEBUG 67 | ex.ToString(); 68 | #else 69 | ex.GetBaseException().Message; 70 | #endif 71 | 72 | public static int Main(params string[] args) 73 | { 74 | try 75 | { 76 | UnsafeMain(args); 77 | 78 | return 0; 79 | } 80 | catch (Exception ex) 81 | { 82 | Console.BackgroundColor = ConsoleColor.Red; 83 | Console.Error.WriteLine(ex.FormatMessage()); 84 | Console.ResetColor(); 85 | 86 | return ex.HResult; 87 | } 88 | } 89 | 90 | public static void UnsafeMain(params string[] args) 91 | { 92 | if (args is not null && args.Length == 1 && args[0].Equals("/?", StringComparison.Ordinal)) 93 | { 94 | Console.WriteLine(@"GetProductKey 95 | A tool to show Windows installation information including product key. 96 | Copyright (c) Olof Lagerkvist, LTR Data, 2021-2022 97 | http://ltr-data.se https://github.com/LTRData 98 | 99 | Syntax to query current machine (Windows only): 100 | GetProductKey 101 | 102 | Syntax to query another machine on network (Windows only): 103 | GetProductKey \\machinename 104 | 105 | Syntax for an offline Windows installation on an attached external harddisk 106 | GetProductKey D:\ 107 | GetProductKey /mnt/external 108 | 109 | Syntax for a virtual machine image (supports vhd, vhdx, vmdk and vdi): 110 | GetProductKey D:\path\image.vhd 111 | GetProductKey /path/image.vhd 112 | 113 | Syntax for a setup ISO or WIM image: 114 | GetProductKey D:\path\windows_setup.iso 115 | GetProductKey /path/windows_setup.iso"); 116 | 117 | return; 118 | } 119 | 120 | var online_root_keys = new ConcurrentBag(); 121 | Task? hardware_product_key = null; 122 | var offline_root_keys = new ConcurrentBag(); 123 | var value_getters = new ConcurrentBag>>(); 124 | var disposables = new ConcurrentBag(); 125 | 126 | if (args is null || args.Length == 0) 127 | { 128 | var key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"); 129 | 130 | if (key is not null) 131 | { 132 | disposables.Add(key); 133 | online_root_keys.Add(key); 134 | value_getters.Add(new($@"\\{Environment.MachineName}", key.GetValue)); 135 | } 136 | 137 | hardware_product_key = Task.Run(() => 138 | { 139 | using var cimSession = CimSession.Create(null); 140 | using var cim = cimSession?.EnumerateInstances(@"root\cimv2", "SoftwareLicensingService").FirstOrDefault(); 141 | 142 | return cim?.CimInstanceProperties["OA3xOriginalProductKey"].Value as string; 143 | }); 144 | } 145 | else 146 | { 147 | Parallel.ForEach(args, arg => 148 | { 149 | try 150 | { 151 | if (arg.StartsWith(@"\\", StringComparison.Ordinal) && 152 | arg.IndexOf('\\', 2) < 0) 153 | { 154 | using var remotehive = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, arg, RegistryView.Registry64); 155 | 156 | var key = remotehive?.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"); 157 | 158 | if (key is not null) 159 | { 160 | disposables.Add(key); 161 | online_root_keys.Add(key); 162 | value_getters.Add(new(arg, key.GetValue)); 163 | } 164 | } 165 | else if (Directory.Exists(arg)) 166 | { 167 | var path = Path.Combine(arg, @"Windows\system32\config\SOFTWARE"); 168 | var hive = new DiscUtilsRegistryHive(File.OpenRead(path), ownership: Ownership.Dispose); 169 | disposables.Add(hive); 170 | var key = hive.Root.OpenSubKey(@"Microsoft\Windows NT\CurrentVersion"); 171 | offline_root_keys.Add(key); 172 | value_getters.Add(new(arg, key.GetValue)); 173 | } 174 | else if (File.Exists(arg) && Path.GetExtension(arg).Equals(".iso", StringComparison.OrdinalIgnoreCase)) 175 | { 176 | var file = File.OpenRead(arg); 177 | disposables.Add(file); 178 | 179 | DiscFileSystem iso; 180 | if (UdfReader.Detect(file)) 181 | { 182 | iso = new UdfReader(file); 183 | } 184 | else 185 | { 186 | iso = new CDReader(file, joliet: true); 187 | } 188 | 189 | var wiminfo = iso.GetFileInfo(@"sources\install.wim"); 190 | if (!wiminfo.Exists) 191 | { 192 | wiminfo = iso.GetFileInfo(@"sources\boot.wim"); 193 | 194 | if (!wiminfo.Exists) 195 | { 196 | throw new FileNotFoundException(@$"Cannot find sources{Path.DirectorySeparatorChar}install.wim in image"); 197 | } 198 | } 199 | 200 | var image = new WimFile(wiminfo.OpenRead()); 201 | 202 | foreach (var fs in image.EnumerateWimImages()) 203 | { 204 | var hive = new DiscUtilsRegistryHive(fs.Value, FileAccess.Read); 205 | var key = hive.Root.OpenSubKey(@"Microsoft\Windows NT\CurrentVersion"); 206 | offline_root_keys.Add(key); 207 | value_getters.Add(new(@$"{arg}{Path.DirectorySeparatorChar}{wiminfo.FullName} index {fs.Key}", name => 208 | { 209 | lock (file) 210 | { 211 | return key.GetValue(name); 212 | } 213 | })); 214 | } 215 | } 216 | else if (File.Exists(arg) && Path.GetExtension(arg).Equals(".wim", StringComparison.OrdinalIgnoreCase)) 217 | { 218 | var file = File.OpenRead(arg); 219 | disposables.Add(file); 220 | 221 | var image = new WimFile(file); 222 | 223 | foreach (var fs in image.EnumerateWimImages()) 224 | { 225 | var hive = new DiscUtilsRegistryHive(fs.Value, FileAccess.Read); 226 | var key = hive.Root.OpenSubKey(@"Microsoft\Windows NT\CurrentVersion"); 227 | offline_root_keys.Add(key); 228 | value_getters.Add(new($"{arg} index {fs.Key}", name => 229 | { 230 | lock (file) 231 | { 232 | return key.GetValue(name); 233 | } 234 | })); 235 | } 236 | } 237 | else if (File.Exists(arg)) 238 | { 239 | var image = VirtualDisk.OpenDisk(arg, FileAccess.Read) 240 | ?? new DiscUtils.Raw.Disk(arg, FileAccess.Read); 241 | 242 | disposables.Add(image); 243 | 244 | foreach (var fs in image.EnumerateVirtualDiskImageFileSystems()) 245 | { 246 | var hive = new DiscUtilsRegistryHive(fs.Value, FileAccess.Read); 247 | var key = hive.Root.OpenSubKey(@"Microsoft\Windows NT\CurrentVersion"); 248 | offline_root_keys.Add(key); 249 | value_getters.Add(new($"{arg} partition {fs.Key}", name => 250 | { 251 | lock (image) 252 | { 253 | return key.GetValue(name); 254 | } 255 | })); 256 | } 257 | } 258 | else 259 | { 260 | throw new FileNotFoundException($"File '{arg}' not found"); 261 | } 262 | } 263 | catch (Exception ex) 264 | { 265 | lock (_syncObj) 266 | { 267 | Console.ForegroundColor = ConsoleColor.Red; 268 | Console.Error.WriteLine($"Error opening '{arg}': {ex.FormatMessage()}"); 269 | Console.ResetColor(); 270 | } 271 | } 272 | }); 273 | } 274 | 275 | Parallel.ForEach(value_getters, obj => 276 | { 277 | try 278 | { 279 | var sb = new StringBuilder() 280 | .AppendLine(obj.Key) 281 | .AppendLine($"Product name: {obj.Value("ProductName")}") 282 | .AppendLine($"Product Id: {obj.Value("ProductId")}") 283 | .AppendLine($"Edition: {obj.Value("EditionID")}") 284 | .AppendLine($"Installation type: {obj.Value("InstallationType")}") 285 | .AppendLine($"Version: {GetVersion(obj.Value)}") 286 | .AppendLine($"Type: {obj.Value("CurrentType")}") 287 | .AppendLine($"Product key: {DecodeProductKey(obj.Value("DigitalProductId") as byte[])}") 288 | .AppendLine($"Install time (UTC): {GetInstallTime(obj.Value)}") 289 | .AppendLine($"Registered owner: {obj.Value("RegisteredOwner")}") 290 | .AppendLine($"Registered organization: {obj.Value("RegisteredOrganization")}"); 291 | 292 | if (hardware_product_key is not null) 293 | { 294 | try 295 | { 296 | sb.AppendLine($"Hardware product key: {hardware_product_key.Result}"); 297 | } 298 | catch (Exception ex) 299 | { 300 | sb.AppendLine($"Failed to get hardware product key: {ex.GetBaseException().Message}"); 301 | } 302 | } 303 | 304 | var msg = sb.ToString(); 305 | 306 | lock (_syncObj) 307 | { 308 | Console.WriteLine(msg); 309 | } 310 | } 311 | catch (Exception ex) 312 | { 313 | lock (_syncObj) 314 | { 315 | Console.ForegroundColor = ConsoleColor.Red; 316 | Console.Error.WriteLine($"Error reading '{obj.Key}': {ex.FormatMessage()}"); 317 | Console.ResetColor(); 318 | } 319 | } 320 | }); 321 | 322 | Parallel.ForEach(disposables.OfType(), obj => obj.Dispose()); 323 | } 324 | 325 | private static string GetVersion(Func value) 326 | { 327 | var currentMajor = value("CurrentMajorVersionNumber"); 328 | if (currentMajor is not null) 329 | { 330 | return $"{currentMajor}.{value("CurrentMinorVersionNumber")}.{value("CurrentBuildNumber")} {value("DisplayVersion")}"; 331 | } 332 | else 333 | { 334 | return $"{value("CurrentVersion")}.{value("CurrentBuildNumber")} {value("CSDVersion")} {value("CSDBuildNumber")}"; 335 | } 336 | } 337 | 338 | private static DateTime? GetInstallTime(Func value) 339 | { 340 | if (value("InstallTime") is long time && 341 | time != 0) 342 | { 343 | return DateTime.FromFileTimeUtc(time); 344 | } 345 | 346 | if (value("InstallDate") is int date && 347 | date != 0) 348 | { 349 | return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(date); 350 | } 351 | 352 | return null; 353 | } 354 | 355 | public static IEnumerable> EnumerateWimImages(this WimFile wim) 356 | { 357 | for (var i = 0; i < wim.ImageCount; i++) 358 | { 359 | var fs = wim.GetImage(i); 360 | var hive = fs.GetFileInfo(@"Windows\system32\config\SOFTWARE"); 361 | 362 | if (hive is not null && hive.Exists) 363 | { 364 | yield return new(i + 1, hive); 365 | } 366 | } 367 | } 368 | 369 | public static IEnumerable> EnumerateVirtualDiskImageFileSystems(this VirtualDisk image) 370 | { 371 | var partitions = image.Partitions; 372 | 373 | if (partitions is not null && partitions.Count > 0) 374 | { 375 | for (var i = 0; i < partitions.Count; i++) 376 | { 377 | var partition = partitions[i]; 378 | 379 | var raw = partition.Open(); 380 | var fsrec = FileSystemManager.DetectFileSystems(raw); 381 | 382 | DiscFileSystem fs; 383 | 384 | try 385 | { 386 | if (fsrec.Count > 0) 387 | { 388 | fs = fsrec[0].Open(raw); 389 | } 390 | else 391 | { 392 | continue; 393 | } 394 | } 395 | catch 396 | { 397 | continue; 398 | } 399 | 400 | var hive = fs.GetFileInfo(@"Windows\system32\config\SOFTWARE"); 401 | if (hive is null || !hive.Exists) 402 | { 403 | hive = fs.GetFileInfo(@"WINNT\system32\config\SOFTWARE"); 404 | } 405 | 406 | if (hive is not null && hive.Exists) 407 | { 408 | yield return new(i + 1, hive); 409 | } 410 | } 411 | } 412 | else 413 | { 414 | var raw = image.Content; 415 | var fsrec = FileSystemManager.DetectFileSystems(raw); 416 | if (fsrec.Count > 0) 417 | { 418 | var fs = fsrec[0].Open(raw); 419 | 420 | var hive = fs.GetFileInfo(@"Windows\system32\config\SOFTWARE"); 421 | if (hive is null || !hive.Exists) 422 | { 423 | hive = fs.GetFileInfo(@"WINNT\system32\config\SOFTWARE"); 424 | } 425 | 426 | if (hive is not null && hive.Exists) 427 | { 428 | yield return new(0, hive); 429 | } 430 | } 431 | } 432 | } 433 | 434 | public static string? DecodeProductKey(ReadOnlySpan data) 435 | { 436 | Span productKey = stackalloc char[29]; 437 | 438 | if (DecodeProductKey(data, productKey)) 439 | { 440 | return productKey.ToString(); 441 | } 442 | 443 | return null; 444 | } 445 | 446 | public static bool DecodeProductKey(ReadOnlySpan data, Span destination) 447 | { 448 | if (data.Length < 67) 449 | { 450 | return false; 451 | } 452 | 453 | Span valueDataBuffer = stackalloc byte[15]; 454 | data.Slice(52, 15).CopyTo(valueDataBuffer); 455 | 456 | var productKey = destination.Slice(0, 29); 457 | 458 | var o = productKey.Length; 459 | 460 | const string chars = "BCDFGHJKMPQRTVWXY2346789"; 461 | 462 | for (var i = 24; i >= 0; i--) 463 | { 464 | var r = 0; 465 | 466 | for (var j = 14; j >= 0; j--) 467 | { 468 | r = (r << 8) | valueDataBuffer[j]; 469 | valueDataBuffer[j] = (byte)(r / 24); 470 | r %= 24; 471 | } 472 | 473 | productKey[--o] = chars[r]; 474 | 475 | if ((i % 5) == 0 && i != 0) 476 | { 477 | productKey[--o] = '-'; 478 | } 479 | } 480 | 481 | if (MemoryExtensions.Equals(productKey, "BBBBB-BBBBB-BBBBB-BBBBB-BBBBB".AsSpan(), StringComparison.Ordinal)) 482 | { 483 | return false; 484 | } 485 | 486 | return true; 487 | } 488 | } 489 | -------------------------------------------------------------------------------- /ImageMBR2GPT/ImageMBR2GPT.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net46;net9.0;net8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ImageMBR2GPT/Program.cs: -------------------------------------------------------------------------------- 1 | using DiscUtils; 2 | using System; 3 | using System.IO; 4 | using System.Linq; 5 | using DiscUtils.Partitions; 6 | using DiscUtils.Raw; 7 | using LTRData.Extensions.Formatting; 8 | using LTRData.Extensions.CommandLine; 9 | using DiscUtils.Streams; 10 | using LTRLib.IO; 11 | using System.Runtime.InteropServices; 12 | 13 | namespace ImageMBR2GPT; 14 | 15 | public static class Program 16 | { 17 | static Program() 18 | { 19 | var asms = new[] 20 | { 21 | typeof(DiscUtils.Vhd.Disk).Assembly, 22 | typeof(DiscUtils.Vhdx.Disk).Assembly, 23 | typeof(DiscUtils.Vmdk.Disk).Assembly, 24 | typeof(DiscUtils.Vdi.Disk).Assembly, 25 | typeof(DiscUtils.Dmg.Disk).Assembly 26 | }; 27 | 28 | foreach (var asm in asms.Distinct()) 29 | { 30 | DiscUtils.Setup.SetupHelper.RegisterAssembly(asm); 31 | } 32 | } 33 | 34 | public static int Main(params string[] args) 35 | { 36 | try 37 | { 38 | UnsafeMain(args); 39 | return 0; 40 | } 41 | catch (Exception ex) 42 | { 43 | Console.ForegroundColor = ConsoleColor.Red; 44 | Console.Error.WriteLine(ex.JoinMessages()); 45 | Console.ResetColor(); 46 | 47 | return ex.HResult; 48 | } 49 | } 50 | 51 | private enum TargetLayout 52 | { 53 | None, 54 | MBR, 55 | GPT 56 | } 57 | 58 | public static void UnsafeMain(params string[] args) 59 | { 60 | var targetLayout = TargetLayout.None; 61 | var access = FileAccess.Read; 62 | 63 | string[]? images = null; 64 | 65 | var cmds = CommandLineParser.ParseCommandLine(args, StringComparer.OrdinalIgnoreCase); 66 | 67 | foreach (var cmd in cmds) 68 | { 69 | if (cmd.Key is "g" or "gpt" 70 | && targetLayout == TargetLayout.None) 71 | { 72 | targetLayout = TargetLayout.GPT; 73 | access = FileAccess.ReadWrite; 74 | } 75 | else if (cmd.Key is "m" or "mbr" 76 | && targetLayout == TargetLayout.None) 77 | { 78 | targetLayout = TargetLayout.MBR; 79 | access = FileAccess.ReadWrite; 80 | } 81 | else if (cmd.Key == "" 82 | && cmd.Value.Length > 0) 83 | { 84 | images = cmd.Value; 85 | } 86 | else 87 | { 88 | Console.WriteLine(@"ImageMBR2GPT 89 | Copyright (c) 2023 - 2024 Olof Lagerkvist, LTR Data, https://ltr-data.se 90 | 91 | Tool for in-place conversion between MBR and GPT partition table formats. 92 | Writes a new partition table with the same partition extents as in existing 93 | partition table, preserving all data within partitions. 94 | 95 | Syntax: 96 | ImageMBR2GPT [--gpt | --mbr] imagefile1 [imagefile2 ...] 97 | 98 | --gpt Write a new GPT partition table replacing existing partition 99 | -g table. 100 | 101 | --mbr Write a new MBR partition table replacing existing partition 102 | -m table. 103 | "); 104 | 105 | return; 106 | } 107 | } 108 | 109 | if (images is null || images.Length == 0) 110 | { 111 | throw new InvalidOperationException("Missing image file path"); 112 | } 113 | 114 | foreach (var image in images) 115 | { 116 | Console.WriteLine($"Opening '{image}'..."); 117 | 118 | using var disk = OpenVirtualDisk(image, access); 119 | 120 | var partition_table = disk.Partitions 121 | ?? throw new NotSupportedException("No partitions detected."); 122 | 123 | var geometry = disk.Geometry 124 | ?? throw new NotSupportedException("Unknown disk geometry"); 125 | 126 | Console.WriteLine($"Current partition table: {partition_table.GetType().Name}"); 127 | 128 | var partitions = partition_table.Partitions; 129 | 130 | Console.WriteLine($"Number of partitions: {partitions.Count}"); 131 | 132 | var extents = partitions.Select((p, i) => (i + 1, p)).ToArray(); 133 | 134 | foreach (var (i, p) in extents) 135 | { 136 | string? active = null; 137 | 138 | if (p is BiosPartitionInfo bios_part 139 | && bios_part.IsActive) 140 | { 141 | active = ", active"; 142 | } 143 | 144 | Console.WriteLine($"Partition {i}, {p.TypeAsString}, offset sector {p.FirstSector}, number of sectors {p.SectorCount} ({SizeFormatting.FormatBytes(p.SectorCount * geometry.BytesPerSector)}){active}"); 145 | } 146 | 147 | if (targetLayout == TargetLayout.None) 148 | { 149 | return; 150 | } 151 | 152 | if (targetLayout == TargetLayout.MBR 153 | && extents.Count(extent => extent.p.GuidType != GuidPartitionTypes.MicrosoftReserved) > 4) 154 | { 155 | throw new NotSupportedException("Cannot convert disks with more partitions than 4 to MBR layout"); 156 | } 157 | 158 | Console.WriteLine($"Do you want to replace the current partition table with a new {targetLayout} partition table? (y/N)"); 159 | 160 | var keychar = Console.ReadKey().KeyChar; 161 | Console.WriteLine(); 162 | if (keychar != 'y') 163 | { 164 | Console.WriteLine("Cancelled"); 165 | return; 166 | } 167 | 168 | Console.WriteLine("Creating new partition table..."); 169 | 170 | PartitionTable new_table = targetLayout switch 171 | { 172 | TargetLayout.GPT => GuidPartitionTable.Initialize(disk), 173 | TargetLayout.MBR => BiosPartitionTable.Initialize(disk), 174 | _ => throw new InvalidOperationException() 175 | }; 176 | 177 | foreach (var (i, p) in extents) 178 | { 179 | Console.WriteLine($"Creating partition {i}, offset sector {p.FirstSector}, number of sectors {p.SectorCount}"); 180 | 181 | if (new_table is GuidPartitionTable guid_table) 182 | { 183 | var partitionType = GuidPartitionTypes.WindowsBasicData; 184 | 185 | if (p is GuidPartitionInfo guidPartition) 186 | { 187 | partitionType = guidPartition.GuidType; 188 | } 189 | 190 | guid_table.Create(p.FirstSector, p.LastSector, partitionType, 0, null); 191 | } 192 | else if (new_table is BiosPartitionTable bios_table) 193 | { 194 | if (p.GuidType == GuidPartitionTypes.MicrosoftReserved) 195 | { 196 | Console.WriteLine("Skipping MSR partition on MBR."); 197 | continue; 198 | } 199 | 200 | var partitionType = BiosPartitionTypes.Ntfs; 201 | var markActive = false; 202 | 203 | if (p is BiosPartitionInfo biosPartition) 204 | { 205 | partitionType = biosPartition.BiosType; 206 | } 207 | else if (p is GuidPartitionInfo guidPartition 208 | && guidPartition.GuidType == GuidPartitionTypes.EfiSystem) 209 | { 210 | partitionType = BiosPartitionTypes.EfiSystem; 211 | markActive = true; 212 | } 213 | 214 | bios_table.CreatePrimaryBySector(p.FirstSector, p.LastSector, partitionType, markActive); 215 | } 216 | } 217 | 218 | Console.WriteLine($"Done. The disk now has a {targetLayout} partition table."); 219 | } 220 | } 221 | 222 | public static VirtualDisk OpenVirtualDisk(string path, FileAccess access) 223 | { 224 | #if NETCOREAPP 225 | if (OperatingSystem.IsWindows()) 226 | { 227 | #endif 228 | if (path.StartsWith(@"\\?\PhysicalDrive", StringComparison.OrdinalIgnoreCase) 229 | || path.StartsWith(@"\\.\PhysicalDrive", StringComparison.OrdinalIgnoreCase)) 230 | { 231 | var stream = new DiskStream(path, access); 232 | return new Disk(stream, ownsStream: Ownership.Dispose); 233 | } 234 | #if NETCOREAPP 235 | } 236 | #endif 237 | 238 | return VirtualDisk.OpenDisk(path, access) ?? new Disk(path, access); 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /ImageMBR2GPT/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "ImageMBR2GPT": { 4 | "commandName": "Project" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /PowerShellFs/PowerShellFs.cs: -------------------------------------------------------------------------------- 1 | using DiscUtils.Internal; 2 | using DokanNet; 3 | using LTRData.Extensions.Native.Memory; 4 | using System; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Management.Automation; 10 | using System.Management.Automation.Runspaces; 11 | using System.Security.AccessControl; 12 | using System.Text; 13 | 14 | namespace PowerShellFs; 15 | 16 | public class PowerShellFs : IDokanOperations 17 | { 18 | public Runspace Runspace { get; } 19 | 20 | public int DirectoryListingTimeoutResetIntervalMs { get; } 21 | 22 | private PowerShell GetPS() 23 | { 24 | var ps = PowerShell.Create(); 25 | ps.Runspace = Runspace; 26 | return ps; 27 | } 28 | 29 | public PowerShellFs(Runspace runspace) 30 | { 31 | runspace.Open(); 32 | Runspace = runspace; 33 | } 34 | 35 | private sealed class FileObject 36 | { 37 | public byte[]? FileData; 38 | } 39 | 40 | public NtStatus CreateFile(ReadOnlyNativeMemory fileNamePtr, NativeFileAccess access, FileShare share, FileMode mode, FileOptions options, FileAttributes attributes, ref DokanFileInfo info) 41 | { 42 | var path = TranslatePath(fileNamePtr.Span); 43 | 44 | if (string.IsNullOrWhiteSpace(path)) 45 | { 46 | return NtStatus.Success; 47 | } 48 | 49 | PSObject finfo; 50 | 51 | lock (Runspace) 52 | { 53 | using var ps = GetPS(); 54 | 55 | finfo = ps.AddCommand("Get-Item").AddParameter("LiteralPath", path).Invoke().FirstOrDefault(); 56 | } 57 | 58 | if (finfo is null && path.EndsWith(@":\", StringComparison.Ordinal)) 59 | { 60 | lock (Runspace) 61 | { 62 | using var ps = GetPS(); 63 | 64 | finfo = ps.AddCommand("Get-PSDrive").AddParameter("Name", path.Remove(path.Length - 2)).Invoke().FirstOrDefault(); 65 | } 66 | } 67 | 68 | if (finfo is null) 69 | { 70 | return NtStatus.ObjectNameNotFound; 71 | } 72 | 73 | if (mode != FileMode.Open && 74 | (!Enum.TryParse(finfo.Properties["Attributes"]?.Value?.ToString(), out var attr) || 75 | (attr.HasFlag(FileAttributes.Directory) ^ info.IsDirectory))) 76 | { 77 | return NtStatus.ObjectNameCollision; 78 | } 79 | 80 | if ((access & (NativeFileAccess.ReadData | NativeFileAccess.GenericRead | NativeFileAccess.WriteData | NativeFileAccess.GenericWrite)) != 0) 81 | { 82 | info.Context = new FileObject(); 83 | } 84 | 85 | return NtStatus.Success; 86 | } 87 | 88 | public void Cleanup(ReadOnlyNativeMemory fileNamePtr, ref DokanFileInfo info) 89 | { 90 | if (info.Context is IDisposable context) 91 | { 92 | context.Dispose(); 93 | info.Context = null; 94 | } 95 | } 96 | 97 | public void CloseFile(ReadOnlyNativeMemory fileNamePtr, ref DokanFileInfo info) 98 | { 99 | } 100 | 101 | public NtStatus ReadFile(ReadOnlyNativeMemory fileNamePtr, NativeMemory buffer, out int bytesRead, long offset, in DokanFileInfo info) 102 | { 103 | var path = TranslatePath(fileNamePtr.Span); 104 | 105 | bytesRead = 0; 106 | 107 | if (info.Context is not FileObject fileObject) 108 | { 109 | return NtStatus.NotImplemented; 110 | } 111 | 112 | var filedata = fileObject.FileData; 113 | 114 | if (filedata is null) 115 | { 116 | lock (fileObject) 117 | { 118 | filedata = fileObject.FileData; 119 | 120 | if (filedata is null) 121 | { 122 | lock (Runspace) 123 | { 124 | using var ps = GetPS(); 125 | 126 | var finfo = ps.AddCommand("Get-Item").AddParameter("LiteralPath", path).Invoke().FirstOrDefault(); 127 | 128 | if (finfo.BaseObject is FileInfo fileInfo) 129 | { 130 | filedata = File.ReadAllBytes(fileInfo.FullName); 131 | } 132 | else if (finfo.Properties["RawData"]?.Value is byte[] rawData) 133 | { 134 | filedata = rawData; 135 | } 136 | else if (finfo.BaseObject is DictionaryEntry entry) 137 | { 138 | if (entry.Value is null) 139 | { 140 | filedata = []; 141 | } 142 | else if (entry.Value is byte[] byteData) 143 | { 144 | filedata = byteData; 145 | } 146 | else 147 | { 148 | filedata = Encoding.Default.GetBytes(entry.Value.ToString()); 149 | } 150 | } 151 | } 152 | 153 | fileObject.FileData = filedata; 154 | } 155 | } 156 | } 157 | 158 | if (filedata is null) 159 | { 160 | return NtStatus.InvalidDeviceRequest; 161 | } 162 | 163 | if (offset > filedata.Length) 164 | { 165 | return NtStatus.Success; 166 | } 167 | 168 | var size = (int)Math.Min(filedata.Length - offset, buffer.Length); 169 | 170 | filedata.AsSpan((int)offset, size).CopyTo(buffer.Span); 171 | bytesRead = size; 172 | return NtStatus.Success; 173 | } 174 | 175 | public NtStatus WriteFile(ReadOnlyNativeMemory fileNamePtr, ReadOnlyNativeMemory buffer, out int bytesWritten, long offset, in DokanFileInfo info) 176 | { 177 | bytesWritten = 0; 178 | return NtStatus.NotImplemented; 179 | } 180 | 181 | public NtStatus FlushFileBuffers(ReadOnlyNativeMemory fileNamePtr, in DokanFileInfo info) => NtStatus.Success; 182 | 183 | public NtStatus GetFileInformation(ReadOnlyNativeMemory fileNamePtr, out ByHandleFileInformation fileInfo, in DokanFileInfo info) 184 | { 185 | var path = TranslatePath(fileNamePtr.Span); 186 | 187 | if (string.IsNullOrWhiteSpace(path)) 188 | { 189 | fileInfo = new ByHandleFileInformation 190 | { 191 | Attributes = FileAttributes.Directory | FileAttributes.System 192 | }; 193 | 194 | return NtStatus.Success; 195 | } 196 | 197 | PSMemberInfoCollection? finfo; 198 | 199 | lock (Runspace) 200 | { 201 | using var ps = GetPS(); 202 | 203 | finfo = ps.AddCommand("Get-Item").AddParameter("LiteralPath", path).Invoke() 204 | .FirstOrDefault()?.Properties; 205 | } 206 | 207 | if (finfo is null && path.EndsWith(@":\", StringComparison.Ordinal)) 208 | { 209 | lock (Runspace) 210 | { 211 | using var ps = GetPS(); 212 | 213 | finfo = ps.AddCommand("Get-PSDrive").AddParameter("Name", path.Remove(path.Length - 2)).Invoke() 214 | .FirstOrDefault()?.Properties; 215 | } 216 | 217 | if (finfo is not null) 218 | { 219 | fileInfo = new ByHandleFileInformation 220 | { 221 | Attributes = FileAttributes.Directory 222 | }; 223 | 224 | return NtStatus.Success; 225 | } 226 | } 227 | 228 | if (finfo is null) 229 | { 230 | fileInfo = default; 231 | return NtStatus.ObjectNameNotFound; 232 | } 233 | 234 | fileInfo = new ByHandleFileInformation 235 | { 236 | Attributes = Enum.TryParse(finfo["Attributes"]?.Value?.ToString(), out var attr) ? attr : 237 | finfo["PSIsContainer"]?.Value as bool? ?? false ? FileAttributes.Directory : FileAttributes.Normal, 238 | CreationTime = finfo["CreationTime"]?.Value as DateTime? ?? finfo["NotBefore"]?.Value as DateTime?, 239 | LastAccessTime = finfo["LastAccessTime"]?.Value as DateTime? ?? finfo["NotBefore"]?.Value as DateTime?, 240 | LastWriteTime = finfo["LastWriteTime"]?.Value as DateTime? ?? finfo["NotBefore"]?.Value as DateTime?, 241 | Length = finfo["Length"]?.Value as long? ?? (finfo["RawData"]?.Value as byte[])?.Length ?? (finfo["Value"]?.Value as string)?.Length ?? 0 242 | }; 243 | 244 | return NtStatus.Success; 245 | } 246 | 247 | public NtStatus FindFiles(ReadOnlyNativeMemory fileNamePtr, out IEnumerable files, in DokanFileInfo info) 248 | => FindFilesWithPattern(fileNamePtr, "*", out files); 249 | 250 | public static string TranslatePath(ReadOnlySpan path) 251 | { 252 | if (path.Length > 0 && path[0] == '\\') 253 | { 254 | path = path.Slice(1); 255 | } 256 | 257 | if (path.IsWhiteSpace()) 258 | { 259 | return string.Empty; 260 | } 261 | 262 | var firstDirDelimiter = path.IndexOf('\\'); 263 | 264 | if (firstDirDelimiter >= 0) 265 | { 266 | return path.ToString().Insert(firstDirDelimiter, ":"); 267 | } 268 | else 269 | { 270 | return path.ToString() + @":\"; 271 | } 272 | } 273 | 274 | public NtStatus FindFilesWithPattern(ReadOnlyNativeMemory fileNamePtr, 275 | ReadOnlyNativeMemory searchPatternPtr, 276 | out IEnumerable files, 277 | in DokanFileInfo info) 278 | => FindFilesWithPattern(fileNamePtr, searchPatternPtr.ToString().Replace('<', '*'), out files); 279 | 280 | public NtStatus FindFilesWithPattern(ReadOnlyNativeMemory fileNamePtr, 281 | string searchPattern, 282 | out IEnumerable files) 283 | { 284 | var path = TranslatePath(fileNamePtr.Span); 285 | 286 | if (path.AsSpan().IndexOfAny('?', '*') < 0) 287 | { 288 | path = Path.Combine(path, searchPattern); 289 | } 290 | 291 | lock (Runspace) 292 | { 293 | using var ps = GetPS(); 294 | 295 | if (path.IndexOf(@":\", StringComparison.Ordinal) < 0 || 296 | path.EndsWith(@":\", StringComparison.Ordinal)) 297 | { 298 | var drives = ps.AddCommand("Get-PSDrive").Invoke().Select(drive => drive.Properties["Name"].Value as string); 299 | 300 | if (fileNamePtr.Span.IndexOfAny('?', '*') >= 0) 301 | { 302 | var regx = Utilities.ConvertWildcardsToRegEx(fileNamePtr.Span.TrimStart('\\').ToString(), ignoreCase: true); 303 | drives = drives.Where(regx); 304 | } 305 | 306 | if (searchPattern != "*") 307 | { 308 | var regx = Utilities.ConvertWildcardsToRegEx(searchPattern, ignoreCase: true); 309 | drives = drives.Where(regx); 310 | } 311 | 312 | files = drives.Select(drive => new FindFileInformation 313 | { 314 | Attributes = FileAttributes.Directory, 315 | FileName = drive.AsMemory() 316 | }); 317 | 318 | return NtStatus.Success; 319 | } 320 | 321 | var entries = ps.AddCommand("Get-Item").AddParameter("Path", path).Invoke().Select(obj => obj.Properties); 322 | 323 | files = entries 324 | .Where(obj => obj["PSChildName"]?.Value is string || obj["Name"]?.Value is string) 325 | .Select(finfo => new FindFileInformation 326 | { 327 | Attributes = Enum.TryParse(finfo["Attributes"]?.Value?.ToString(), out var attr) ? attr : 328 | finfo["PSIsContainer"]?.Value as bool? ?? false ? FileAttributes.Directory : FileAttributes.Normal, 329 | CreationTime = finfo["CreationTime"]?.Value as DateTime? ?? finfo["NotBefore"]?.Value as DateTime?, 330 | LastAccessTime = finfo["LastAccessTime"]?.Value as DateTime? ?? finfo["NotBefore"]?.Value as DateTime?, 331 | LastWriteTime = finfo["LastWriteTime"]?.Value as DateTime? ?? finfo["NotBefore"]?.Value as DateTime?, 332 | Length = finfo["Length"]?.Value as long? ?? (finfo["RawData"]?.Value as byte[])?.Length ?? (finfo["Value"]?.Value as string)?.Length ?? 0, 333 | FileName = (finfo["PSChildName"]?.Value as string ?? finfo["Name"]?.Value as string).AsMemory() 334 | }); 335 | 336 | return NtStatus.Success; 337 | } 338 | } 339 | 340 | public NtStatus SetFileAttributes(ReadOnlyNativeMemory fileNamePtr, FileAttributes attributes, in DokanFileInfo info) => NtStatus.NotImplemented; 341 | 342 | public NtStatus SetFileTime(ReadOnlyNativeMemory fileNamePtr, DateTime? creationTime, DateTime? lastAccessTime, DateTime? lastWriteTime, in DokanFileInfo info) => NtStatus.NotImplemented; 343 | 344 | public NtStatus DeleteFile(ReadOnlyNativeMemory fileNamePtr, in DokanFileInfo info) => NtStatus.NotImplemented; 345 | 346 | public NtStatus DeleteDirectory(ReadOnlyNativeMemory fileNamePtr, in DokanFileInfo info) => NtStatus.NotImplemented; 347 | 348 | public NtStatus MoveFile(ReadOnlyNativeMemory oldName, ReadOnlyNativeMemory newName, bool replace, ref DokanFileInfo info) => NtStatus.NotImplemented; 349 | 350 | public NtStatus SetEndOfFile(ReadOnlyNativeMemory fileNamePtr, long length, in DokanFileInfo info) => NtStatus.NotImplemented; 351 | 352 | public NtStatus SetAllocationSize(ReadOnlyNativeMemory fileNamePtr, long length, in DokanFileInfo info) => NtStatus.NotImplemented; 353 | 354 | public NtStatus LockFile(ReadOnlyNativeMemory fileNamePtr, long offset, long length, in DokanFileInfo info) => NtStatus.NotImplemented; 355 | 356 | public NtStatus UnlockFile(ReadOnlyNativeMemory fileNamePtr, long offset, long length, in DokanFileInfo info) => NtStatus.NotImplemented; 357 | 358 | public NtStatus GetDiskFreeSpace(out long freeBytesAvailable, out long totalNumberOfBytes, out long totalNumberOfFreeBytes, in DokanFileInfo info) 359 | { 360 | freeBytesAvailable = 0; 361 | totalNumberOfBytes = 0; 362 | totalNumberOfFreeBytes = 0; 363 | return NtStatus.Success; 364 | } 365 | 366 | public NtStatus GetVolumeInformation(NativeMemory volumeLabel, out FileSystemFeatures features, NativeMemory fileSystemName, out uint maximumComponentLength, ref uint volumeSerialNumber, in DokanFileInfo info) 367 | { 368 | volumeLabel.SetString("PowerShell"); 369 | features = FileSystemFeatures.ReadOnlyVolume | FileSystemFeatures.UnicodeOnDisk; 370 | fileSystemName.SetString("PowerShell"); 371 | maximumComponentLength = 260; 372 | return NtStatus.Success; 373 | } 374 | 375 | public NtStatus GetFileSecurity(ReadOnlyNativeMemory fileNamePtr, out FileSystemSecurity security, AccessControlSections sections, in DokanFileInfo info) 376 | { 377 | security = null!; 378 | return NtStatus.NotImplemented; 379 | } 380 | 381 | public NtStatus SetFileSecurity(ReadOnlyNativeMemory fileNamePtr, FileSystemSecurity security, AccessControlSections sections, in DokanFileInfo info) => NtStatus.NotImplemented; 382 | 383 | public NtStatus Mounted(ReadOnlyNativeMemory drive, in DokanFileInfo info) => NtStatus.Success; 384 | 385 | public NtStatus Unmounted(in DokanFileInfo info) => NtStatus.Success; 386 | 387 | public NtStatus FindStreams(ReadOnlyNativeMemory fileNamePtr, out IEnumerable streams, in DokanFileInfo info) 388 | { 389 | streams = null!; 390 | return NtStatus.NotImplemented; 391 | } 392 | } 393 | -------------------------------------------------------------------------------- /PowerShellFs/PowerShellFs.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Exe 6 | net48 7 | true 8 | PowerShellFs - Virtual file system for PowerShell drives 9 | PowerShellFs 10 | Copyright © LTR Data, Olof Lagerkvist 2020-2022 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /PowerShellFs/Program.cs: -------------------------------------------------------------------------------- 1 | using DokanNet; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections.ObjectModel; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | using System.Management.Automation.Runspaces; 8 | using System.Reflection; 9 | 10 | namespace PowerShellFs; 11 | 12 | public static class Program 13 | { 14 | private static class CollectionExtensions 15 | { 16 | private static readonly MethodInfo GetItemsMethod = typeof(Collection).GetProperty("Items", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).GetGetMethod(nonPublic: true); 17 | private static readonly ParameterExpression CollectionParam = Expression.Parameter(typeof(Collection), "collection"); 18 | public static Func, IList> GetItems { get; } = Expression.Lambda, IList>>(Expression.Call(CollectionParam, GetItemsMethod), CollectionParam).Compile(); 19 | 20 | private static readonly ParameterExpression ListParam = Expression.Parameter(typeof(List), "list"); 21 | private static readonly FieldInfo ListItemsField = typeof(List).GetField("_items", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 22 | public static Func, T[]> GetArray { get; } = Expression.Lambda, T[]>>(Expression.Field(ListParam, ListItemsField), ListParam).Compile(); 23 | } 24 | 25 | public static T[] GetBuffer(this Collection collection) 26 | { 27 | if (CollectionExtensions.GetItems(collection) is List list) 28 | { 29 | return CollectionExtensions.GetArray(list); 30 | } 31 | 32 | var array = new T[collection.Count]; 33 | collection.CopyTo(array, 0); 34 | return array; 35 | } 36 | 37 | public static void Main(params string[] args) 38 | { 39 | Dokan.Init(); 40 | 41 | RunspaceConnectionInfo? ci = null; 42 | 43 | if (args?.FirstOrDefault() is string host) 44 | { 45 | ci = new WSManConnectionInfo 46 | { 47 | ComputerName = args[0], 48 | AuthenticationMechanism = AuthenticationMechanism.Default 49 | }; 50 | } 51 | 52 | using var runspace = ci is not null ? RunspaceFactory.CreateRunspace(ci) : RunspaceFactory.CreateRunspace(); 53 | 54 | var fs = new PowerShellFs(runspace); 55 | 56 | Console.CancelKeyPress += (sender, e) => 57 | { 58 | Dokan.RemoveMountPoint("Q:"); 59 | e.Cancel = true; 60 | }; 61 | 62 | fs.Mount("Q:", DokanOptions.WriteProtection); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /PowerShellFs/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | // General Information about an assembly is controlled through the following 4 | // set of attributes. Change these attribute values to modify the information 5 | // associated with an assembly. 6 | 7 | // Setting ComVisible to false makes the types in this assembly not visible 8 | // to COM components. If you need to access a type in this assembly from 9 | // COM, set the ComVisible attribute to true on that type. 10 | [assembly: ComVisible(false)] 11 | 12 | // The following GUID is for the ID of the typelib if this project is exposed to COM 13 | [assembly: Guid("11538566-2549-43b3-b9be-da870143849f")] 14 | 15 | // Version information for an assembly consists of the following four values: 16 | // 17 | // Major Version 18 | // Minor Version 19 | // Build Number 20 | // Revision 21 | // 22 | // You can specify all the values or you can default the Build and Revision Numbers 23 | // by using the '*' as shown below: 24 | // [assembly: AssemblyVersion("1.0.*")] 25 | -------------------------------------------------------------------------------- /PowerShellFs/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "PowerShellFs": { 4 | "commandName": "Project" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /RecentCleanup/Interop.IWshRuntimeLibrary.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LTRData/SystemTools/d7136ccf6b9ab87aa125cabf56a28ee4378bc5d1/RecentCleanup/Interop.IWshRuntimeLibrary.dll -------------------------------------------------------------------------------- /RecentCleanup/Program.cs: -------------------------------------------------------------------------------- 1 | using IWshRuntimeLibrary; 2 | using System; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | using System.Runtime.Versioning; 8 | using System.Threading; 9 | using File = System.IO.File; 10 | 11 | namespace RecentCleanup; 12 | 13 | public static class Program 14 | { 15 | private readonly static string RecentFolder = Environment.GetFolderPath(Environment.SpecialFolder.Recent); 16 | 17 | #if NETCOREAPP 18 | [SupportedOSPlatform("windows")] 19 | #endif 20 | public static void Main(params string[] args) 21 | { 22 | if (args is not null 23 | && args.SingleOrDefault() == "--trace") 24 | { 25 | Trace.Listeners.Add(new ConsoleTraceListener(useErrorStream: true)); 26 | } 27 | 28 | var shell = new WshShell(); 29 | 30 | using var watcher = new FileSystemWatcher(RecentFolder, "*.lnk"); 31 | 32 | for (; ; ) 33 | { 34 | Thread.Sleep(4_000); 35 | 36 | foreach (var link in Directory.EnumerateFiles(RecentFolder, "*.lnk")) 37 | { 38 | try 39 | { 40 | Trace.WriteLine($"{DateTime.UtcNow}: Analyzing shortcut '{link}'"); 41 | 42 | var shortcut = (IWshShortcut)shell.CreateShortcut(link); 43 | 44 | var targetPath = shortcut.TargetPath; 45 | 46 | Marshal.ReleaseComObject(shortcut); 47 | 48 | if (string.IsNullOrWhiteSpace(targetPath)) 49 | { 50 | continue; 51 | } 52 | 53 | try 54 | { 55 | Trace.WriteLine($"{DateTime.UtcNow}: Checking for target file '{targetPath}'"); 56 | 57 | if (!Directory.Exists(targetPath) 58 | && !File.Exists(targetPath)) 59 | { 60 | File.Delete(link); 61 | 62 | Trace.WriteLine($"{DateTime.UtcNow}: Removed shortcut '{link}'"); 63 | } 64 | } 65 | catch (Exception ex) 66 | { 67 | Trace.WriteLine($"{DateTime.UtcNow}: Failed to remove shortcut '{link}': {ex}"); 68 | } 69 | } 70 | catch (Exception ex) 71 | { 72 | Trace.WriteLine($"{DateTime.UtcNow}: Failed to check shortcut '{link}': {ex}"); 73 | } 74 | } 75 | 76 | Trace.WriteLine($"{DateTime.UtcNow}: Waiting for changes to '{RecentFolder}'"); 77 | 78 | watcher.WaitForChanged(WatcherChangeTypes.Changed); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /RecentCleanup/RecentCleanup.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net48;net8.0;net9.0 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /SessionPowerSaver/Program.cs: -------------------------------------------------------------------------------- 1 | using LTRData.Extensions.Formatting; 2 | using LTRLib.IO; 3 | using LTRLib.Services.WTS; 4 | using Microsoft.Win32; 5 | using System; 6 | using System.Collections.Concurrent; 7 | using System.Collections.Generic; 8 | using System.Diagnostics; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Security.Principal; 12 | using System.Threading; 13 | using System.Threading.Tasks; 14 | 15 | namespace SessionPowerSaver; 16 | 17 | public static class Program 18 | { 19 | private static Process CurrentProcess { get; } = Process.GetCurrentProcess(); 20 | 21 | private static WindowsIdentity CurrentUser { get; } = WindowsIdentity.GetCurrent(); 22 | 23 | private static readonly StreamWriter log = new(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), $"Session_{CurrentProcess.SessionId}.log"), append: true) 24 | { 25 | AutoFlush = true 26 | }; 27 | 28 | private static void LogWrite(string? message) 29 | { 30 | message = $"{DateTime.UtcNow:o} Thread {Environment.CurrentManagedThreadId:X5} {message}"; 31 | 32 | ThreadPool.QueueUserWorkItem(message => 33 | { 34 | Trace.WriteLine(message); 35 | 36 | lock (log) 37 | { 38 | log.WriteLine(message); 39 | } 40 | }, message); 41 | } 42 | 43 | static Program() 44 | { 45 | AppDomain.CurrentDomain.UnhandledException += (sender, e) => LogWrite(e.ExceptionObject.ToString()); 46 | } 47 | 48 | public static int Main() 49 | { 50 | LogWrite("Starting up SessionPowerSaver"); 51 | 52 | var currentProcessTree = new List(); 53 | try 54 | { 55 | currentProcessTree.Add(CurrentProcess.Id); 56 | for (var ppid = (int)CurrentProcess.QueryBasicInformation().ParentProcessId; 57 | ppid != 0;) 58 | { 59 | currentProcessTree.Add(ppid); 60 | 61 | using var p = Process.GetProcessById(ppid); 62 | if (p.HasExited) 63 | { 64 | break; 65 | } 66 | 67 | ppid = (int)p.QueryBasicInformation().ParentProcessId; 68 | } 69 | } 70 | catch 71 | { 72 | } 73 | 74 | var suspended = new ConcurrentDictionary(); 75 | 76 | var rc = 0; 77 | 78 | try 79 | { 80 | ServiceLoop(currentProcessTree, suspended); 81 | } 82 | catch (Exception ex) 83 | { 84 | LogWrite(ex.ToString()); 85 | rc = ex.HResult; 86 | } 87 | 88 | Parallel.ForEach(suspended, item => 89 | { 90 | try 91 | { 92 | using var suspended_process = SafeOpenProcess(item.Key); 93 | 94 | if (suspended_process is not null && item.Value == suspended_process.StartTime) 95 | { 96 | LogWrite($"Resuming process {suspended_process.Id} ({suspended_process.ProcessName})"); 97 | suspended_process.Resume(); 98 | } 99 | } 100 | catch (Exception ex) 101 | { 102 | LogWrite($"Failed to resume process {item.Key}: {ex}"); 103 | } 104 | }); 105 | 106 | LogWrite($"Exiting SessionPowerSaver 0x{rc:X}"); 107 | 108 | return rc; 109 | } 110 | 111 | private static void ServiceLoop(IReadOnlyList currentProcessTree, ConcurrentDictionary suspended) 112 | { 113 | using var sync = new ManualResetEvent(initialState: true); 114 | 115 | SystemEvents.SessionSwitch += (_, _) => sync.Set(); 116 | 117 | for (; ; ) 118 | { 119 | var session_state = WTS.CurrentSessionInfo.SessionState; 120 | 121 | sync.Reset(); 122 | 123 | var is_connected = session_state <= ConnectState.Connected; 124 | 125 | LogWrite($"Session is {session_state}"); 126 | 127 | Parallel.ForEach(WTS.CurrentSessionProcesses 128 | .TakeWhile(p => !sync.WaitOne(0)) 129 | .Where(p => p.UserSid == CurrentUser.User && 130 | !currentProcessTree.Contains(p.ProcessId) && 131 | p.TotalProcessorTime.TotalMinutes > 6d), p => 132 | { 133 | if (sync.WaitOne(0)) 134 | { 135 | return; 136 | } 137 | 138 | if (suspended.TryGetValue(p.ProcessId, out var item)) 139 | { 140 | using var suspended_process = SafeOpenProcess(p.ProcessId); 141 | 142 | if (suspended_process is null || item != suspended_process.StartTime) 143 | { 144 | LogWrite($"Previous process {p.ProcessId} with start time {item} no longer exists"); 145 | suspended.TryRemove(p.ProcessId, out item); 146 | } 147 | else if (is_connected) 148 | { 149 | LogWrite($"Resuming process {p.ProcessId} ({p.ProcessName})"); 150 | suspended_process.Resume(); 151 | suspended.TryRemove(p.ProcessId, out item); 152 | return; 153 | } 154 | else 155 | { 156 | return; 157 | } 158 | } 159 | 160 | if (is_connected) 161 | { 162 | return; 163 | } 164 | 165 | using var process = SafeOpenProcess(p.ProcessId); 166 | 167 | if (process is null || 168 | process.MainWindowHandle == IntPtr.Zero || 169 | !process.Responding) 170 | { 171 | return; 172 | } 173 | 174 | var process_time = DateTime.Now - process.StartTime; 175 | 176 | var cpu = p.TotalProcessorTime.TotalMilliseconds / process_time.TotalMilliseconds; 177 | 178 | if (cpu > 0.1) 179 | { 180 | LogWrite($"Process {p.ProcessId} ({p.ProcessName}, '{process.MainWindowTitle}') CPU usage is {100 * cpu:0.0}%. Suspending..."); 181 | 182 | process.Suspend(); 183 | suspended[p.ProcessId] = process.StartTime; 184 | } 185 | }); 186 | 187 | LogWrite("Waiting"); 188 | 189 | if (sync.WaitOne(TimeSpan.FromMinutes(60))) 190 | { 191 | LogWrite("Session change"); 192 | } 193 | else 194 | { 195 | LogWrite("Timeout"); 196 | } 197 | } 198 | } 199 | 200 | private static Process? SafeOpenProcess(int processId) 201 | { 202 | try 203 | { 204 | return Process.GetProcessById(processId); 205 | } 206 | catch (Exception ex) 207 | { 208 | LogWrite($"Failed to open process {processId}: {ex.JoinMessages(" -> ")}"); 209 | return null; 210 | } 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /SessionPowerSaver/SessionPowerSaver.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | WinExe 6 | net48;net9.0-windows;net8.0-windows 7 | true 8 | SessionPowerSaver 9 | SessionPowerSaver 10 | Copyright © LTR Data, Olof Lagerkvist 2021-2022 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /StripeBlockSwap/Program.cs: -------------------------------------------------------------------------------- 1 | using LTRData.Extensions.CommandLine; 2 | using LTRData.Extensions.Formatting; 3 | using LTRLib.IO; 4 | using System; 5 | using System.IO; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace StripeBlockSwap; 10 | 11 | public static class Program 12 | { 13 | public static async Task Main(params string[] args) 14 | { 15 | try 16 | { 17 | using var tokenSource = new CancellationTokenSource(); 18 | 19 | Console.CancelKeyPress += (sender, e) => 20 | { 21 | tokenSource.Cancel(); 22 | e.Cancel = true; 23 | }; 24 | 25 | var token = tokenSource.Token; 26 | 27 | return await MainAsync(args, token).ConfigureAwait(false); 28 | } 29 | catch (Exception ex) 30 | { 31 | Console.ForegroundColor = ConsoleColor.Red; 32 | Console.Error.WriteLine(ex.JoinMessages()); 33 | Console.ResetColor(); 34 | return ex.HResult; 35 | } 36 | } 37 | 38 | public static async Task MainAsync(string[] args, CancellationToken cancellationToken) 39 | { 40 | var cmds = CommandLineParser.ParseCommandLine(args, StringComparer.Ordinal); 41 | 42 | var blockSize = 0L; 43 | var inoffset = 0L; 44 | var outoffset = 0L; 45 | 46 | string? infile = null; 47 | string? outfile = null; 48 | 49 | foreach (var cmd in cmds) 50 | { 51 | if (cmd.Key == "bsize" && cmd.Value.Length == 1 && 52 | SizeFormatting.TryParseSuffixedSize(cmd.Value[0], out blockSize)) 53 | { 54 | } 55 | else if (cmd.Key == "inoffset" && cmd.Value.Length == 1 && 56 | SizeFormatting.TryParseSuffixedSize(cmd.Value[0], out inoffset)) 57 | { 58 | } 59 | else if (cmd.Key == "outoffset" && cmd.Value.Length == 1 && 60 | SizeFormatting.TryParseSuffixedSize(cmd.Value[0], out outoffset)) 61 | { 62 | } 63 | else if (cmd.Key == "in" && cmd.Value.Length == 1) 64 | { 65 | infile = cmd.Value[0]; 66 | } 67 | else if (cmd.Key == "out" && cmd.Value.Length == 1) 68 | { 69 | outfile = cmd.Value[0]; 70 | } 71 | else 72 | { 73 | Console.WriteLine(@"Syntax: 74 | StripeBlockSwap --bsize=blocksize [--inoffset=inputoffset] [--outoffset=outputoffset] [--in=inputfile] [--out=outputfile]"); 75 | 76 | return 100; 77 | } 78 | } 79 | 80 | if (blockSize <= 0) 81 | { 82 | Console.WriteLine(@"Syntax: 83 | StripeBlockSwap --bsize=blocksize [--inoffset=inputoffset] [--outoffset=outputoffset] [--in=inputfile] [--out=outputfile]"); 84 | 85 | return 100; 86 | } 87 | 88 | cancellationToken.ThrowIfCancellationRequested(); 89 | 90 | var buffer = new byte[blockSize]; 91 | 92 | Console.Error.WriteLine($"Using block size {blockSize} bytes"); 93 | 94 | Console.Error.WriteLine($"Opening input file {(infile is not null and not "-" ? infile : "stdin")}"); 95 | 96 | using var input = infile is null or "-" 97 | ? Console.OpenStandardInput() 98 | : OperatingSystem.IsWindows() && infile.StartsWith(@"\\?\", StringComparison.Ordinal) 99 | ? new DiskStream(infile, FileAccess.Read) 100 | : File.OpenRead(infile); 101 | 102 | if (inoffset != 0) 103 | { 104 | Console.Error.WriteLine($"Starting at input offset {inoffset}"); 105 | input.Seek(inoffset, SeekOrigin.Current); 106 | } 107 | 108 | cancellationToken.ThrowIfCancellationRequested(); 109 | 110 | Console.Error.WriteLine($"Opening output file {(outfile is not null and not "-" ? outfile : "stdout")}"); 111 | 112 | using var output = outfile is null or "-" 113 | ? Console.OpenStandardOutput() 114 | : OperatingSystem.IsWindows() && outfile.StartsWith(@"\\?\", StringComparison.Ordinal) 115 | ? new DiskStream(outfile, FileAccess.ReadWrite) 116 | : outoffset == 0 117 | ? File.Create(outfile) 118 | : File.OpenWrite(outfile); 119 | 120 | if (outoffset != 0) 121 | { 122 | Console.Error.WriteLine($"Starting at output offset {outoffset}"); 123 | } 124 | 125 | for (var blockCount = 0L; ; blockCount++) 126 | { 127 | cancellationToken.ThrowIfCancellationRequested(); 128 | 129 | Console.Error.Write($"Reading block {blockCount}...\r"); 130 | 131 | var length = await input.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); 132 | 133 | if (length == 0) 134 | { 135 | Console.Error.WriteLine(); 136 | Console.Error.WriteLine($"Done, wrote {blockCount * blockSize} bytes."); 137 | break; 138 | } 139 | 140 | if ((blockCount & 1) == 0) 141 | { 142 | output.Position = outoffset + blockSize * (blockCount + 1); 143 | } 144 | else 145 | { 146 | output.Position = outoffset + blockSize * (blockCount - 1); 147 | } 148 | 149 | cancellationToken.ThrowIfCancellationRequested(); 150 | 151 | Console.Error.Write($"Writing block {blockCount}...\r"); 152 | 153 | await output.WriteAsync(buffer.AsMemory(0, length), cancellationToken).ConfigureAwait(false); 154 | 155 | if (length < blockSize) 156 | { 157 | Console.Error.WriteLine(); 158 | Console.Error.WriteLine($"Done, wrote {blockCount * blockSize + length} bytes."); 159 | break; 160 | } 161 | } 162 | 163 | return 0; 164 | } 165 | } -------------------------------------------------------------------------------- /StripeBlockSwap/StripeBlockSwap.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net9.0;net8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /SystemTools.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.2.32526.322 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SessionPowerSaver", "SessionPowerSaver\SessionPowerSaver.csproj", "{1681916F-85D9-4C18-BF87-6EC9E9BA2C6E}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppxActivate", "AppxActivate\AppxActivate.csproj", "{EE9584E8-8BFA-481B-BF65-F5FCEE4952D2}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiskVolumes", "DiskVolumes\DiskVolumes.csproj", "{D1BDBFD9-8647-4890-A737-F1B2C7AAABC1}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dssearch", "dssearch\dssearch.csproj", "{9592E582-9E5D-4B09-A42B-CA2E2C48900F}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "telnets", "telnets\telnets.csproj", "{E2FF95B7-FD54-4664-9A16-8A5AE2C56559}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerShellFs", "PowerShellFs\PowerShellFs.csproj", "{E3CA69B8-2419-4898-B561-251941F04B58}" 17 | EndProject 18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D557391E-B9DC-4205-990C-059953BA236B}" 19 | ProjectSection(SolutionItems) = preProject 20 | Directory.Build.props = Directory.Build.props 21 | EndProjectSection 22 | EndProject 23 | Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "Dataviewer", "Dataviewer\Dataviewer.vbproj", "{9FC71E50-8777-43BB-A907-BEE69AB1F301}" 24 | EndProject 25 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GetProductKey", "GetProductKey\GetProductKey.csproj", "{6BE6F995-CC04-45EA-B97F-4810FE643922}" 26 | EndProject 27 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageMBR2GPT", "ImageMBR2GPT\ImageMBR2GPT.csproj", "{302D061E-631F-439F-B849-5D4707305FED}" 28 | EndProject 29 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ipcalc", "ipcalc\ipcalc.csproj", "{A46C179E-F0DC-4ECF-9DA8-17F0CA2F11AF}" 30 | EndProject 31 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StripeBlockSwap", "StripeBlockSwap\StripeBlockSwap.csproj", "{6C5AC1C4-B34A-4523-8796-8474E0454D0B}" 32 | EndProject 33 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "waitps", "waitps\waitps.csproj", "{5F0421F2-010C-4D24-8A67-F4DEA22B6614}" 34 | EndProject 35 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RecentCleanup", "RecentCleanup\RecentCleanup.csproj", "{F154A202-3137-40D1-9B16-F5FD005D6D28}" 36 | EndProject 37 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "waitwin", "waitwin\waitwin.csproj", "{06FE382E-9464-444E-B7D1-52CA14B25EC1}" 38 | EndProject 39 | Global 40 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 41 | Debug|Any CPU = Debug|Any CPU 42 | Debug|x64 = Debug|x64 43 | Debug|x86 = Debug|x86 44 | Release|Any CPU = Release|Any CPU 45 | Release|x64 = Release|x64 46 | Release|x86 = Release|x86 47 | EndGlobalSection 48 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 49 | {1681916F-85D9-4C18-BF87-6EC9E9BA2C6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 50 | {1681916F-85D9-4C18-BF87-6EC9E9BA2C6E}.Debug|Any CPU.Build.0 = Debug|Any CPU 51 | {1681916F-85D9-4C18-BF87-6EC9E9BA2C6E}.Debug|x64.ActiveCfg = Debug|Any CPU 52 | {1681916F-85D9-4C18-BF87-6EC9E9BA2C6E}.Debug|x64.Build.0 = Debug|Any CPU 53 | {1681916F-85D9-4C18-BF87-6EC9E9BA2C6E}.Debug|x86.ActiveCfg = Debug|Any CPU 54 | {1681916F-85D9-4C18-BF87-6EC9E9BA2C6E}.Debug|x86.Build.0 = Debug|Any CPU 55 | {1681916F-85D9-4C18-BF87-6EC9E9BA2C6E}.Release|Any CPU.ActiveCfg = Release|Any CPU 56 | {1681916F-85D9-4C18-BF87-6EC9E9BA2C6E}.Release|Any CPU.Build.0 = Release|Any CPU 57 | {1681916F-85D9-4C18-BF87-6EC9E9BA2C6E}.Release|x64.ActiveCfg = Release|Any CPU 58 | {1681916F-85D9-4C18-BF87-6EC9E9BA2C6E}.Release|x64.Build.0 = Release|Any CPU 59 | {1681916F-85D9-4C18-BF87-6EC9E9BA2C6E}.Release|x86.ActiveCfg = Release|Any CPU 60 | {1681916F-85D9-4C18-BF87-6EC9E9BA2C6E}.Release|x86.Build.0 = Release|Any CPU 61 | {EE9584E8-8BFA-481B-BF65-F5FCEE4952D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 62 | {EE9584E8-8BFA-481B-BF65-F5FCEE4952D2}.Debug|Any CPU.Build.0 = Debug|Any CPU 63 | {EE9584E8-8BFA-481B-BF65-F5FCEE4952D2}.Debug|x64.ActiveCfg = Debug|Any CPU 64 | {EE9584E8-8BFA-481B-BF65-F5FCEE4952D2}.Debug|x64.Build.0 = Debug|Any CPU 65 | {EE9584E8-8BFA-481B-BF65-F5FCEE4952D2}.Debug|x86.ActiveCfg = Debug|Any CPU 66 | {EE9584E8-8BFA-481B-BF65-F5FCEE4952D2}.Debug|x86.Build.0 = Debug|Any CPU 67 | {EE9584E8-8BFA-481B-BF65-F5FCEE4952D2}.Release|Any CPU.ActiveCfg = Release|Any CPU 68 | {EE9584E8-8BFA-481B-BF65-F5FCEE4952D2}.Release|Any CPU.Build.0 = Release|Any CPU 69 | {EE9584E8-8BFA-481B-BF65-F5FCEE4952D2}.Release|x64.ActiveCfg = Release|Any CPU 70 | {EE9584E8-8BFA-481B-BF65-F5FCEE4952D2}.Release|x64.Build.0 = Release|Any CPU 71 | {EE9584E8-8BFA-481B-BF65-F5FCEE4952D2}.Release|x86.ActiveCfg = Release|Any CPU 72 | {EE9584E8-8BFA-481B-BF65-F5FCEE4952D2}.Release|x86.Build.0 = Release|Any CPU 73 | {D1BDBFD9-8647-4890-A737-F1B2C7AAABC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 74 | {D1BDBFD9-8647-4890-A737-F1B2C7AAABC1}.Debug|Any CPU.Build.0 = Debug|Any CPU 75 | {D1BDBFD9-8647-4890-A737-F1B2C7AAABC1}.Debug|x64.ActiveCfg = Debug|Any CPU 76 | {D1BDBFD9-8647-4890-A737-F1B2C7AAABC1}.Debug|x64.Build.0 = Debug|Any CPU 77 | {D1BDBFD9-8647-4890-A737-F1B2C7AAABC1}.Debug|x86.ActiveCfg = Debug|Any CPU 78 | {D1BDBFD9-8647-4890-A737-F1B2C7AAABC1}.Debug|x86.Build.0 = Debug|Any CPU 79 | {D1BDBFD9-8647-4890-A737-F1B2C7AAABC1}.Release|Any CPU.ActiveCfg = Release|Any CPU 80 | {D1BDBFD9-8647-4890-A737-F1B2C7AAABC1}.Release|Any CPU.Build.0 = Release|Any CPU 81 | {D1BDBFD9-8647-4890-A737-F1B2C7AAABC1}.Release|x64.ActiveCfg = Release|Any CPU 82 | {D1BDBFD9-8647-4890-A737-F1B2C7AAABC1}.Release|x64.Build.0 = Release|Any CPU 83 | {D1BDBFD9-8647-4890-A737-F1B2C7AAABC1}.Release|x86.ActiveCfg = Release|Any CPU 84 | {D1BDBFD9-8647-4890-A737-F1B2C7AAABC1}.Release|x86.Build.0 = Release|Any CPU 85 | {9592E582-9E5D-4B09-A42B-CA2E2C48900F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 86 | {9592E582-9E5D-4B09-A42B-CA2E2C48900F}.Debug|Any CPU.Build.0 = Debug|Any CPU 87 | {9592E582-9E5D-4B09-A42B-CA2E2C48900F}.Debug|x64.ActiveCfg = Debug|Any CPU 88 | {9592E582-9E5D-4B09-A42B-CA2E2C48900F}.Debug|x64.Build.0 = Debug|Any CPU 89 | {9592E582-9E5D-4B09-A42B-CA2E2C48900F}.Debug|x86.ActiveCfg = Debug|Any CPU 90 | {9592E582-9E5D-4B09-A42B-CA2E2C48900F}.Debug|x86.Build.0 = Debug|Any CPU 91 | {9592E582-9E5D-4B09-A42B-CA2E2C48900F}.Release|Any CPU.ActiveCfg = Release|Any CPU 92 | {9592E582-9E5D-4B09-A42B-CA2E2C48900F}.Release|Any CPU.Build.0 = Release|Any CPU 93 | {9592E582-9E5D-4B09-A42B-CA2E2C48900F}.Release|x64.ActiveCfg = Release|Any CPU 94 | {9592E582-9E5D-4B09-A42B-CA2E2C48900F}.Release|x64.Build.0 = Release|Any CPU 95 | {9592E582-9E5D-4B09-A42B-CA2E2C48900F}.Release|x86.ActiveCfg = Release|Any CPU 96 | {9592E582-9E5D-4B09-A42B-CA2E2C48900F}.Release|x86.Build.0 = Release|Any CPU 97 | {E2FF95B7-FD54-4664-9A16-8A5AE2C56559}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 98 | {E2FF95B7-FD54-4664-9A16-8A5AE2C56559}.Debug|Any CPU.Build.0 = Debug|Any CPU 99 | {E2FF95B7-FD54-4664-9A16-8A5AE2C56559}.Debug|x64.ActiveCfg = Debug|Any CPU 100 | {E2FF95B7-FD54-4664-9A16-8A5AE2C56559}.Debug|x64.Build.0 = Debug|Any CPU 101 | {E2FF95B7-FD54-4664-9A16-8A5AE2C56559}.Debug|x86.ActiveCfg = Debug|Any CPU 102 | {E2FF95B7-FD54-4664-9A16-8A5AE2C56559}.Debug|x86.Build.0 = Debug|Any CPU 103 | {E2FF95B7-FD54-4664-9A16-8A5AE2C56559}.Release|Any CPU.ActiveCfg = Release|Any CPU 104 | {E2FF95B7-FD54-4664-9A16-8A5AE2C56559}.Release|Any CPU.Build.0 = Release|Any CPU 105 | {E2FF95B7-FD54-4664-9A16-8A5AE2C56559}.Release|x64.ActiveCfg = Release|Any CPU 106 | {E2FF95B7-FD54-4664-9A16-8A5AE2C56559}.Release|x64.Build.0 = Release|Any CPU 107 | {E2FF95B7-FD54-4664-9A16-8A5AE2C56559}.Release|x86.ActiveCfg = Release|Any CPU 108 | {E2FF95B7-FD54-4664-9A16-8A5AE2C56559}.Release|x86.Build.0 = Release|Any CPU 109 | {E3CA69B8-2419-4898-B561-251941F04B58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 110 | {E3CA69B8-2419-4898-B561-251941F04B58}.Debug|Any CPU.Build.0 = Debug|Any CPU 111 | {E3CA69B8-2419-4898-B561-251941F04B58}.Debug|x64.ActiveCfg = Debug|Any CPU 112 | {E3CA69B8-2419-4898-B561-251941F04B58}.Debug|x64.Build.0 = Debug|Any CPU 113 | {E3CA69B8-2419-4898-B561-251941F04B58}.Debug|x86.ActiveCfg = Debug|Any CPU 114 | {E3CA69B8-2419-4898-B561-251941F04B58}.Debug|x86.Build.0 = Debug|Any CPU 115 | {E3CA69B8-2419-4898-B561-251941F04B58}.Release|Any CPU.ActiveCfg = Release|Any CPU 116 | {E3CA69B8-2419-4898-B561-251941F04B58}.Release|Any CPU.Build.0 = Release|Any CPU 117 | {E3CA69B8-2419-4898-B561-251941F04B58}.Release|x64.ActiveCfg = Release|Any CPU 118 | {E3CA69B8-2419-4898-B561-251941F04B58}.Release|x64.Build.0 = Release|Any CPU 119 | {E3CA69B8-2419-4898-B561-251941F04B58}.Release|x86.ActiveCfg = Release|Any CPU 120 | {E3CA69B8-2419-4898-B561-251941F04B58}.Release|x86.Build.0 = Release|Any CPU 121 | {9FC71E50-8777-43BB-A907-BEE69AB1F301}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 122 | {9FC71E50-8777-43BB-A907-BEE69AB1F301}.Debug|Any CPU.Build.0 = Debug|Any CPU 123 | {9FC71E50-8777-43BB-A907-BEE69AB1F301}.Debug|x64.ActiveCfg = Debug|Any CPU 124 | {9FC71E50-8777-43BB-A907-BEE69AB1F301}.Debug|x64.Build.0 = Debug|Any CPU 125 | {9FC71E50-8777-43BB-A907-BEE69AB1F301}.Debug|x86.ActiveCfg = Debug|Any CPU 126 | {9FC71E50-8777-43BB-A907-BEE69AB1F301}.Debug|x86.Build.0 = Debug|Any CPU 127 | {9FC71E50-8777-43BB-A907-BEE69AB1F301}.Release|Any CPU.ActiveCfg = Release|Any CPU 128 | {9FC71E50-8777-43BB-A907-BEE69AB1F301}.Release|Any CPU.Build.0 = Release|Any CPU 129 | {9FC71E50-8777-43BB-A907-BEE69AB1F301}.Release|x64.ActiveCfg = Release|Any CPU 130 | {9FC71E50-8777-43BB-A907-BEE69AB1F301}.Release|x64.Build.0 = Release|Any CPU 131 | {9FC71E50-8777-43BB-A907-BEE69AB1F301}.Release|x86.ActiveCfg = Release|Any CPU 132 | {9FC71E50-8777-43BB-A907-BEE69AB1F301}.Release|x86.Build.0 = Release|Any CPU 133 | {6BE6F995-CC04-45EA-B97F-4810FE643922}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 134 | {6BE6F995-CC04-45EA-B97F-4810FE643922}.Debug|Any CPU.Build.0 = Debug|Any CPU 135 | {6BE6F995-CC04-45EA-B97F-4810FE643922}.Debug|x64.ActiveCfg = Debug|Any CPU 136 | {6BE6F995-CC04-45EA-B97F-4810FE643922}.Debug|x64.Build.0 = Debug|Any CPU 137 | {6BE6F995-CC04-45EA-B97F-4810FE643922}.Debug|x86.ActiveCfg = Debug|Any CPU 138 | {6BE6F995-CC04-45EA-B97F-4810FE643922}.Debug|x86.Build.0 = Debug|Any CPU 139 | {6BE6F995-CC04-45EA-B97F-4810FE643922}.Release|Any CPU.ActiveCfg = Release|Any CPU 140 | {6BE6F995-CC04-45EA-B97F-4810FE643922}.Release|Any CPU.Build.0 = Release|Any CPU 141 | {6BE6F995-CC04-45EA-B97F-4810FE643922}.Release|x64.ActiveCfg = Release|Any CPU 142 | {6BE6F995-CC04-45EA-B97F-4810FE643922}.Release|x64.Build.0 = Release|Any CPU 143 | {6BE6F995-CC04-45EA-B97F-4810FE643922}.Release|x86.ActiveCfg = Release|Any CPU 144 | {6BE6F995-CC04-45EA-B97F-4810FE643922}.Release|x86.Build.0 = Release|Any CPU 145 | {302D061E-631F-439F-B849-5D4707305FED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 146 | {302D061E-631F-439F-B849-5D4707305FED}.Debug|Any CPU.Build.0 = Debug|Any CPU 147 | {302D061E-631F-439F-B849-5D4707305FED}.Debug|x64.ActiveCfg = Debug|Any CPU 148 | {302D061E-631F-439F-B849-5D4707305FED}.Debug|x64.Build.0 = Debug|Any CPU 149 | {302D061E-631F-439F-B849-5D4707305FED}.Debug|x86.ActiveCfg = Debug|Any CPU 150 | {302D061E-631F-439F-B849-5D4707305FED}.Debug|x86.Build.0 = Debug|Any CPU 151 | {302D061E-631F-439F-B849-5D4707305FED}.Release|Any CPU.ActiveCfg = Release|Any CPU 152 | {302D061E-631F-439F-B849-5D4707305FED}.Release|Any CPU.Build.0 = Release|Any CPU 153 | {302D061E-631F-439F-B849-5D4707305FED}.Release|x64.ActiveCfg = Release|Any CPU 154 | {302D061E-631F-439F-B849-5D4707305FED}.Release|x64.Build.0 = Release|Any CPU 155 | {302D061E-631F-439F-B849-5D4707305FED}.Release|x86.ActiveCfg = Release|Any CPU 156 | {302D061E-631F-439F-B849-5D4707305FED}.Release|x86.Build.0 = Release|Any CPU 157 | {A46C179E-F0DC-4ECF-9DA8-17F0CA2F11AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 158 | {A46C179E-F0DC-4ECF-9DA8-17F0CA2F11AF}.Debug|Any CPU.Build.0 = Debug|Any CPU 159 | {A46C179E-F0DC-4ECF-9DA8-17F0CA2F11AF}.Debug|x64.ActiveCfg = Debug|Any CPU 160 | {A46C179E-F0DC-4ECF-9DA8-17F0CA2F11AF}.Debug|x64.Build.0 = Debug|Any CPU 161 | {A46C179E-F0DC-4ECF-9DA8-17F0CA2F11AF}.Debug|x86.ActiveCfg = Debug|Any CPU 162 | {A46C179E-F0DC-4ECF-9DA8-17F0CA2F11AF}.Debug|x86.Build.0 = Debug|Any CPU 163 | {A46C179E-F0DC-4ECF-9DA8-17F0CA2F11AF}.Release|Any CPU.ActiveCfg = Release|Any CPU 164 | {A46C179E-F0DC-4ECF-9DA8-17F0CA2F11AF}.Release|Any CPU.Build.0 = Release|Any CPU 165 | {A46C179E-F0DC-4ECF-9DA8-17F0CA2F11AF}.Release|x64.ActiveCfg = Release|Any CPU 166 | {A46C179E-F0DC-4ECF-9DA8-17F0CA2F11AF}.Release|x64.Build.0 = Release|Any CPU 167 | {A46C179E-F0DC-4ECF-9DA8-17F0CA2F11AF}.Release|x86.ActiveCfg = Release|Any CPU 168 | {A46C179E-F0DC-4ECF-9DA8-17F0CA2F11AF}.Release|x86.Build.0 = Release|Any CPU 169 | {6C5AC1C4-B34A-4523-8796-8474E0454D0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 170 | {6C5AC1C4-B34A-4523-8796-8474E0454D0B}.Debug|Any CPU.Build.0 = Debug|Any CPU 171 | {6C5AC1C4-B34A-4523-8796-8474E0454D0B}.Debug|x64.ActiveCfg = Debug|Any CPU 172 | {6C5AC1C4-B34A-4523-8796-8474E0454D0B}.Debug|x64.Build.0 = Debug|Any CPU 173 | {6C5AC1C4-B34A-4523-8796-8474E0454D0B}.Debug|x86.ActiveCfg = Debug|Any CPU 174 | {6C5AC1C4-B34A-4523-8796-8474E0454D0B}.Debug|x86.Build.0 = Debug|Any CPU 175 | {6C5AC1C4-B34A-4523-8796-8474E0454D0B}.Release|Any CPU.ActiveCfg = Release|Any CPU 176 | {6C5AC1C4-B34A-4523-8796-8474E0454D0B}.Release|Any CPU.Build.0 = Release|Any CPU 177 | {6C5AC1C4-B34A-4523-8796-8474E0454D0B}.Release|x64.ActiveCfg = Release|Any CPU 178 | {6C5AC1C4-B34A-4523-8796-8474E0454D0B}.Release|x64.Build.0 = Release|Any CPU 179 | {6C5AC1C4-B34A-4523-8796-8474E0454D0B}.Release|x86.ActiveCfg = Release|Any CPU 180 | {6C5AC1C4-B34A-4523-8796-8474E0454D0B}.Release|x86.Build.0 = Release|Any CPU 181 | {5F0421F2-010C-4D24-8A67-F4DEA22B6614}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 182 | {5F0421F2-010C-4D24-8A67-F4DEA22B6614}.Debug|Any CPU.Build.0 = Debug|Any CPU 183 | {5F0421F2-010C-4D24-8A67-F4DEA22B6614}.Debug|x64.ActiveCfg = Debug|Any CPU 184 | {5F0421F2-010C-4D24-8A67-F4DEA22B6614}.Debug|x64.Build.0 = Debug|Any CPU 185 | {5F0421F2-010C-4D24-8A67-F4DEA22B6614}.Debug|x86.ActiveCfg = Debug|Any CPU 186 | {5F0421F2-010C-4D24-8A67-F4DEA22B6614}.Debug|x86.Build.0 = Debug|Any CPU 187 | {5F0421F2-010C-4D24-8A67-F4DEA22B6614}.Release|Any CPU.ActiveCfg = Release|Any CPU 188 | {5F0421F2-010C-4D24-8A67-F4DEA22B6614}.Release|Any CPU.Build.0 = Release|Any CPU 189 | {5F0421F2-010C-4D24-8A67-F4DEA22B6614}.Release|x64.ActiveCfg = Release|Any CPU 190 | {5F0421F2-010C-4D24-8A67-F4DEA22B6614}.Release|x64.Build.0 = Release|Any CPU 191 | {5F0421F2-010C-4D24-8A67-F4DEA22B6614}.Release|x86.ActiveCfg = Release|Any CPU 192 | {5F0421F2-010C-4D24-8A67-F4DEA22B6614}.Release|x86.Build.0 = Release|Any CPU 193 | {F154A202-3137-40D1-9B16-F5FD005D6D28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 194 | {F154A202-3137-40D1-9B16-F5FD005D6D28}.Debug|Any CPU.Build.0 = Debug|Any CPU 195 | {F154A202-3137-40D1-9B16-F5FD005D6D28}.Debug|x64.ActiveCfg = Debug|Any CPU 196 | {F154A202-3137-40D1-9B16-F5FD005D6D28}.Debug|x64.Build.0 = Debug|Any CPU 197 | {F154A202-3137-40D1-9B16-F5FD005D6D28}.Debug|x86.ActiveCfg = Debug|Any CPU 198 | {F154A202-3137-40D1-9B16-F5FD005D6D28}.Debug|x86.Build.0 = Debug|Any CPU 199 | {F154A202-3137-40D1-9B16-F5FD005D6D28}.Release|Any CPU.ActiveCfg = Release|Any CPU 200 | {F154A202-3137-40D1-9B16-F5FD005D6D28}.Release|Any CPU.Build.0 = Release|Any CPU 201 | {F154A202-3137-40D1-9B16-F5FD005D6D28}.Release|x64.ActiveCfg = Release|Any CPU 202 | {F154A202-3137-40D1-9B16-F5FD005D6D28}.Release|x64.Build.0 = Release|Any CPU 203 | {F154A202-3137-40D1-9B16-F5FD005D6D28}.Release|x86.ActiveCfg = Release|Any CPU 204 | {F154A202-3137-40D1-9B16-F5FD005D6D28}.Release|x86.Build.0 = Release|Any CPU 205 | {06FE382E-9464-444E-B7D1-52CA14B25EC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 206 | {06FE382E-9464-444E-B7D1-52CA14B25EC1}.Debug|Any CPU.Build.0 = Debug|Any CPU 207 | {06FE382E-9464-444E-B7D1-52CA14B25EC1}.Debug|x64.ActiveCfg = Debug|Any CPU 208 | {06FE382E-9464-444E-B7D1-52CA14B25EC1}.Debug|x64.Build.0 = Debug|Any CPU 209 | {06FE382E-9464-444E-B7D1-52CA14B25EC1}.Debug|x86.ActiveCfg = Debug|Any CPU 210 | {06FE382E-9464-444E-B7D1-52CA14B25EC1}.Debug|x86.Build.0 = Debug|Any CPU 211 | {06FE382E-9464-444E-B7D1-52CA14B25EC1}.Release|Any CPU.ActiveCfg = Release|Any CPU 212 | {06FE382E-9464-444E-B7D1-52CA14B25EC1}.Release|Any CPU.Build.0 = Release|Any CPU 213 | {06FE382E-9464-444E-B7D1-52CA14B25EC1}.Release|x64.ActiveCfg = Release|Any CPU 214 | {06FE382E-9464-444E-B7D1-52CA14B25EC1}.Release|x64.Build.0 = Release|Any CPU 215 | {06FE382E-9464-444E-B7D1-52CA14B25EC1}.Release|x86.ActiveCfg = Release|Any CPU 216 | {06FE382E-9464-444E-B7D1-52CA14B25EC1}.Release|x86.Build.0 = Release|Any CPU 217 | EndGlobalSection 218 | GlobalSection(SolutionProperties) = preSolution 219 | HideSolutionNode = FALSE 220 | EndGlobalSection 221 | GlobalSection(ExtensibilityGlobals) = postSolution 222 | SolutionGuid = {7D580973-9945-4852-B219-718F1BB32ACC} 223 | EndGlobalSection 224 | EndGlobal 225 | -------------------------------------------------------------------------------- /dssearch/Program.cs: -------------------------------------------------------------------------------- 1 | #if NETFRAMEWORK 2 | using LTRData.Extensions.Buffers; 3 | using LTRLib.Extensions; 4 | #endif 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Diagnostics; 8 | using System.DirectoryServices; 9 | using System.DirectoryServices.AccountManagement; 10 | using System.Linq; 11 | using System.Reflection; 12 | using System.Security.Principal; 13 | 14 | namespace dssearch; 15 | 16 | public static class ActiveDirectoryInfo 17 | { 18 | static IEnumerable EnumerateMessages(this Exception? ex) 19 | { 20 | while (ex is not null) 21 | { 22 | yield return ex.Message; 23 | ex = ex.InnerException; 24 | } 25 | 26 | yield break; 27 | } 28 | 29 | public static int Main(string[] args) 30 | { 31 | try 32 | { 33 | return InternalMain(args); 34 | } 35 | catch (Exception ex) 36 | { 37 | Console.ForegroundColor = ConsoleColor.Red; 38 | Console.Error.WriteLine(string.Join(" -> ", ex.EnumerateMessages().ToArray())); 39 | Console.ResetColor(); 40 | return -1; 41 | } 42 | } 43 | 44 | public static int InternalMain(string[] args) 45 | { 46 | DirectoryEntry? entry = null; 47 | 48 | // Examples to specify a domain 49 | //var adPath = "LDAP://DC=olofdom,DC=se"; 50 | 51 | foreach (var arg in args) 52 | { 53 | if (arg.StartsWith("LDAP://", StringComparison.OrdinalIgnoreCase)) 54 | { 55 | if (entry is not null) 56 | { 57 | entry.Dispose(); 58 | entry = null; 59 | } 60 | 61 | entry = new DirectoryEntry(arg); 62 | } 63 | 64 | if (entry is null) 65 | { 66 | entry = UserPrincipal.Current.GetUnderlyingObject() as DirectoryEntry; 67 | if (entry is null) 68 | { 69 | Console.Error.WriteLine("No current LDAP user."); 70 | return 1; 71 | } 72 | 73 | entry = entry.Parent; 74 | } 75 | 76 | // Examples to search for posix account values 77 | //var adSearch = new DirectorySearcher(new DirectoryEntry(adPath), "(&(objectClass=user)(sAMAccountName=olof))"); 78 | //var adSearch = new DirectorySearcher(new DirectoryEntry(adPath), "(&(objectClass=user)(uidNumber=*)(msSFU30Password=*))"); 79 | 80 | DirectorySearcher adSearch; 81 | 82 | if (string.IsNullOrEmpty(arg)) 83 | { 84 | adSearch = new DirectorySearcher(entry); 85 | } 86 | else 87 | { 88 | adSearch = new DirectorySearcher(entry, arg); 89 | } 90 | 91 | using (adSearch) 92 | { 93 | foreach (var userentry in adSearch.FindAll().OfType().Select(u => u.GetDirectoryEntry())) 94 | { 95 | using (userentry) 96 | { 97 | Console.WriteLine(); 98 | Console.WriteLine("------------"); 99 | 100 | var props = userentry.Properties; 101 | 102 | foreach (var prop in props.OfType()) 103 | { 104 | Console.WriteLine(FormatProp(prop)); 105 | } 106 | 107 | // How to clear a field: 108 | //userentry.Properties["mail"].Clear(); 109 | //userentry.CommitChanges(); 110 | } 111 | } 112 | } 113 | } 114 | 115 | if (Debugger.IsAttached) 116 | { 117 | Console.ReadKey(); 118 | } 119 | 120 | return 0; 121 | } 122 | 123 | private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) => throw new NotImplementedException(); 124 | 125 | public static void PrintProp(DirectoryEntry user) 126 | { 127 | if (user is not null) 128 | { 129 | var props = user.Properties; 130 | 131 | foreach (var prop in props.OfType()) 132 | { 133 | Console.WriteLine(FormatProp(prop)); 134 | } 135 | } 136 | } 137 | 138 | public static string FormatProp(PropertyValueCollection prop) 139 | { 140 | return prop.Value switch 141 | { 142 | byte[] guidBytes when guidBytes.Length == 16 && prop.PropertyName.Contains("GUID", StringComparison.OrdinalIgnoreCase) 143 | => $"{prop.PropertyName} = {new Guid(guidBytes)}", 144 | 145 | byte[] sidBytes when prop.PropertyName.Contains("Sid", StringComparison.OrdinalIgnoreCase) 146 | => $"{prop.PropertyName} = {new SecurityIdentifier(sidBytes, 0)}", 147 | 148 | _ => $"{prop.PropertyName} = {FormatProp(prop.Value)}" 149 | }; 150 | } 151 | 152 | private static string FormatProp(object? propValue) 153 | { 154 | if (propValue is null) 155 | { 156 | return "(null)"; 157 | } 158 | else if (propValue is string str) 159 | { 160 | return str; 161 | } 162 | else if (propValue is byte[] bytes) 163 | { 164 | if (bytes.Length > 32) 165 | { 166 | return Convert.ToBase64String(bytes); 167 | } 168 | else 169 | { 170 | return BitConverter.ToString(bytes); 171 | } 172 | } 173 | else if (propValue is object[] array) 174 | { 175 | return @$"{{ 176 | {string.Join(";" + Environment.NewLine, Array.ConvertAll(array, o => $" {FormatProp(o)}"))} 177 | }}"; 178 | } 179 | else if (propValue.GetType() is IReflect reflect) 180 | { 181 | var type = reflect.UnderlyingSystemType; 182 | 183 | if (type.GUID.Equals(Guid.Empty)) 184 | { 185 | return "(unknown)"; 186 | } 187 | 188 | var obj = Convert.ChangeType(propValue, type); 189 | 190 | return obj.ToString() ?? "(null)"; 191 | } 192 | else 193 | { 194 | return propValue.ToString() ?? "(null)"; 195 | } 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /dssearch/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using System.Runtime.Versioning; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | 8 | // Setting ComVisible to false makes the types in this assembly not visible 9 | // to COM components. If you need to access a type in this assembly from 10 | // COM, set the ComVisible attribute to true on that type. 11 | [assembly: ComVisible(false)] 12 | 13 | // The following GUID is for the ID of the typelib if this project is exposed to COM 14 | [assembly: Guid("aa4cbd34-a37b-46df-9442-0a75ae58f9ba")] 15 | 16 | // Version information for an assembly consists of the following four values: 17 | // 18 | // Major Version 19 | // Minor Version 20 | // Build Number 21 | // Revision 22 | // 23 | // You can specify all the values or you can default the Build and Revision Numbers 24 | // by using the '*' as shown below: 25 | // [assembly: AssemblyVersion("1.0.*")] 26 | 27 | [assembly: SupportedOSPlatform("windows")] 28 | -------------------------------------------------------------------------------- /dssearch/dssearch.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Exe 6 | net35;net40;net9.0;net8.0 7 | dssearch - Directory Services search tool 8 | dssearch 9 | Copyright © LTR Data, Olof Lagerkvist 2015-2022 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ipcalc/Program.cs: -------------------------------------------------------------------------------- 1 | using LTRData.Extensions.Buffers; 2 | using LTRData.Extensions.Formatting; 3 | using LTRData.Extensions.Split; 4 | using LTRLib.Net; 5 | using System; 6 | using System.Net; 7 | using System.Net.Sockets; 8 | 9 | namespace ipcalc; 10 | 11 | public static class Program 12 | { 13 | public static int Main(params string[] args) 14 | { 15 | foreach (var arg in args) 16 | { 17 | try 18 | { 19 | CalculateAddress(arg.AsSpan()); 20 | } 21 | catch (Exception ex) 22 | { 23 | Console.ForegroundColor = ConsoleColor.Red; 24 | Console.Error.WriteLine(ex.JoinMessages()); 25 | Console.ResetColor(); 26 | } 27 | } 28 | 29 | return 0; 30 | } 31 | 32 | #if NETCOREAPP || NETSTANDARD2_1_OR_GREATER 33 | private static IPAddress ParseIP(ReadOnlySpan address) => IPAddress.Parse(address); 34 | 35 | private static byte ParseByte(ReadOnlySpan chars) => byte.Parse(chars); 36 | #else 37 | private static IPAddress ParseIP(ReadOnlySpan address) => IPAddress.Parse(address.ToString()); 38 | 39 | private static byte ParseByte(ReadOnlySpan chars) => byte.Parse(chars.ToString()); 40 | #endif 41 | 42 | public static void CalculateAddress(ReadOnlySpan arg) 43 | { 44 | var startAddress = arg.TokenEnum('-').ElementAtOrDefault(0); 45 | var endAddress = arg.TokenEnum('-').ElementAtOrDefault(1); 46 | var netAddress = arg.TokenEnum('/').ElementAtOrDefault(0); 47 | var bitCount = arg.TokenEnum('/').ElementAtOrDefault(1); 48 | var maskNetwork = arg.TokenEnum('%').ElementAtOrDefault(0); 49 | var mask = arg.TokenEnum('%').ElementAtOrDefault(1); 50 | 51 | var ranges = new IPAddressRanges(AddressFamily.InterNetwork); 52 | 53 | (IPAddress Network, IPAddress Mask, IPAddress Broadcast, byte BitCount) network; 54 | 55 | if (!startAddress.IsEmpty && !endAddress.IsEmpty && bitCount.IsEmpty) 56 | { 57 | network = ranges.CalculateNetwork(ParseIP(startAddress), ParseIP(endAddress)); 58 | } 59 | else if (!netAddress.IsEmpty && !bitCount.IsEmpty && endAddress.IsEmpty) 60 | { 61 | network = ranges.CalculateNetwork(ParseIP(netAddress), ParseByte(bitCount)); 62 | } 63 | else if (!maskNetwork.IsEmpty && !mask.IsEmpty) 64 | { 65 | network = ranges.CalculateNetwork(ParseIP(maskNetwork), ParseMask(ParseIP(mask))); 66 | } 67 | else 68 | { 69 | throw new ArgumentException("Invalid address range syntax"); 70 | } 71 | 72 | Console.WriteLine(@$"Network: {network.Network}/{network.BitCount} - {network.Broadcast} mask {network.Mask}"); 73 | } 74 | 75 | private static byte ParseMask(IPAddress address) 76 | { 77 | byte bits = 0; 78 | 79 | var bytes = address.GetAddressBytes(); 80 | 81 | if (BitConverter.IsLittleEndian) 82 | { 83 | Array.Reverse(bytes); 84 | } 85 | 86 | var lastOne = false; 87 | 88 | byte addressBits = (byte)(bytes.Length * 8); 89 | 90 | for (byte i = 0; i < addressBits; i++) 91 | { 92 | if (lastOne) 93 | { 94 | if (!bytes.GetBit(i)) 95 | { 96 | throw new ArgumentException($"Invalid mask: {address}"); 97 | } 98 | } 99 | else 100 | { 101 | if (bytes.GetBit(i)) 102 | { 103 | bits = i; 104 | lastOne = true; 105 | } 106 | } 107 | } 108 | 109 | return (byte)(addressBits - bits); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /ipcalc/ipcalc.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net48;netstandard2.1;net9.0;net8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /telnets/Program.cs: -------------------------------------------------------------------------------- 1 | using LTRData.Extensions.Buffers; 2 | using LTRData.Extensions.Formatting; 3 | using LTRLib.Extensions; 4 | using LTRLib.IO; 5 | using LTRLib.LTRGeneric; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Diagnostics; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Net; 12 | using System.Net.Security; 13 | using System.Net.Sockets; 14 | using System.Runtime.InteropServices; 15 | using System.Threading; 16 | 17 | #pragma warning disable IDE0079 // Remove unnecessary suppression 18 | #pragma warning disable IDE0056 // Use index operator 19 | 20 | namespace telnets; 21 | 22 | public static class Program 23 | { 24 | public static readonly string telnet_exe = Environment.GetEnvironmentVariable("TELNET") ?? GetTelnetPath(); 25 | 26 | private static string GetTelnetPath() 27 | { 28 | #if !NETFRAMEWORK 29 | if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 30 | { 31 | return "telnet"; 32 | } 33 | #endif 34 | return Path.Combine(Environment.SystemDirectory, "telnet.exe"); 35 | } 36 | 37 | public static void WriteError(string msg) 38 | { 39 | Console.ForegroundColor = ConsoleColor.Red; 40 | Console.Error.WriteLine(msg); 41 | Console.ResetColor(); 42 | } 43 | 44 | public static int Main(params string[] args) 45 | { 46 | var dispobjs = new DisposableList(); 47 | 48 | try 49 | { 50 | if (args is null || args.Length < 1) 51 | { 52 | WriteError("Syntax: telnets [options] host [port]"); 53 | return -1; 54 | } 55 | 56 | string remote_host; 57 | var remote_port = 992; 58 | var options = Enumerable.Empty(); 59 | 60 | if (args.Length >= 2) 61 | { 62 | remote_port = int.Parse(args[args.Length - 1]); 63 | remote_host = args[args.Length - 2]; 64 | options = args.Take(args.Length - 2); 65 | } 66 | else 67 | { 68 | remote_host = args[args.Length - 1]; 69 | } 70 | 71 | Console.WriteLine($"Connecting to '{remote_host}' at port {remote_port}"); 72 | 73 | var remote_socket = IOSupport.OpenTcpIpSocket(remote_host, remote_port); 74 | remote_socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); 75 | var remote_raw_stream = new NetworkStream(remote_socket); 76 | 77 | dispobjs.Add(remote_raw_stream); 78 | 79 | Console.WriteLine("Connected, applying security"); 80 | 81 | var remote_stream = new SslStream(remote_raw_stream); 82 | 83 | dispobjs.Insert(0, remote_stream); 84 | 85 | remote_stream.AuthenticateAsClient(remote_host); 86 | 87 | Console.WriteLine("Setting up local forwarder"); 88 | 89 | var local_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 90 | 91 | dispobjs.Add(local_listener); 92 | 93 | local_listener.Bind(new IPEndPoint(IPAddress.Loopback, 0)); 94 | var local_port = (local_listener.LocalEndPoint as IPEndPoint)?.Port; 95 | local_listener.Listen(1); 96 | 97 | var telnet_arguments = options 98 | .Append(IPAddress.Loopback.ToString()) 99 | .Append(local_port.ToString() ?? "") 100 | .Join(' '); 101 | 102 | Console.WriteLine($"Starting '{telnet_exe}' with arguments '{telnet_arguments}'"); 103 | 104 | var telnet_start_info = new ProcessStartInfo 105 | { 106 | FileName = telnet_exe, 107 | Arguments = telnet_arguments, 108 | UseShellExecute = false 109 | }; 110 | 111 | var telnet_ps = Process.Start(telnet_start_info); 112 | 113 | if (telnet_ps is null) 114 | { 115 | return -1; 116 | } 117 | 118 | dispobjs.Add(telnet_ps); 119 | var local_socket = local_listener.Accept(); 120 | local_listener.Close(); 121 | local_socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); 122 | 123 | var local_stream = new NetworkStream(local_socket); 124 | 125 | dispobjs.Add(local_stream); 126 | 127 | var threads = new List 128 | { 129 | CreateForwarder("Inbound", remote_stream, local_stream, () => local_socket.Shutdown(SocketShutdown.Send)), 130 | CreateForwarder("Outbound", local_stream, remote_stream, () => remote_socket.Shutdown(SocketShutdown.Send)) 131 | }; 132 | threads.ForEach(t => t.Start()); 133 | 134 | threads.ForEach(t => t.Join()); 135 | 136 | telnet_ps.WaitForExit(); 137 | 138 | return telnet_ps.ExitCode; 139 | } 140 | catch (Exception ex) 141 | { 142 | WriteError(ex.JoinMessages()); 143 | return 1; 144 | } 145 | finally 146 | { 147 | dispobjs.Dispose(); 148 | } 149 | } 150 | 151 | public static Thread CreateForwarder(string name, Stream source_stream, Stream target_stream, Action finalizer) 152 | { 153 | return new Thread(() => 154 | { 155 | try 156 | { 157 | source_stream.CopyTo(target_stream); 158 | } 159 | catch (IOException) 160 | { 161 | } 162 | catch (ObjectDisposedException) 163 | { 164 | } 165 | finally 166 | { 167 | finalizer?.Invoke(); 168 | } 169 | }) 170 | { 171 | Name = name, 172 | IsBackground = true 173 | }; 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /telnets/telnets.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Exe 6 | net35;net40;net9.0;net8.0 7 | telnets - Client for telnet over SSL/TLS 8 | telnets 9 | Copyright (c) 2017-2022 LTR Data, Olof Lagerkvist 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /waitps/Program.cs: -------------------------------------------------------------------------------- 1 | using LTRData.Extensions.CommandLine; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace waitps; 10 | 11 | public static class Program 12 | { 13 | private static readonly string[] exeFileExtensions = [".exe", ".com", ".dll"]; 14 | 15 | public static int Main(params string[] args) 16 | { 17 | var cmds = CommandLineParser.ParseCommandLine(args, StringComparer.Ordinal); 18 | 19 | var waitAny = false; 20 | 21 | string[] processes = []; 22 | 23 | foreach (var cmd in cmds) 24 | { 25 | switch (cmd.Key) 26 | { 27 | case "a": 28 | waitAny = true; 29 | break; 30 | 31 | case "": 32 | processes = cmd.Value; 33 | break; 34 | 35 | default: 36 | Console.WriteLine($@"Process wait utility - Copyright (c) 2024-2025 Olof Lagerkvist, LTR Data 37 | https://ltr-data.se/opencode.html 38 | 39 | Syntax: 40 | 41 | waitps [-a] pid1 [pid2 ...] 42 | 43 | -a Wait for any of specified processes to exit. Otherwise, waits for all 44 | of specified processes to exit. 45 | 46 | Processes can be specified as numeric process id or process name."); 47 | 48 | return -1; 49 | } 50 | } 51 | 52 | var pslist = new List(); 53 | 54 | try 55 | { 56 | foreach (var process in processes) 57 | { 58 | if (int.TryParse(process, out var pid)) 59 | { 60 | pslist.Add(Process.GetProcessById(pid)); 61 | } 62 | else 63 | { 64 | var psName = process; 65 | 66 | if (exeFileExtensions.Contains(Path.GetExtension(psName), StringComparer.OrdinalIgnoreCase)) 67 | { 68 | psName = psName.Remove(psName.Length - 4); 69 | } 70 | 71 | pslist.AddRange(Process.GetProcessesByName(psName)); 72 | } 73 | } 74 | 75 | if (pslist.Count == 0) 76 | { 77 | Console.WriteLine("No process found"); 78 | return 0; 79 | } 80 | 81 | foreach (var ps in pslist) 82 | { 83 | Console.WriteLine($"{ps.Id,7} {ps.ProcessName}"); 84 | } 85 | 86 | if (pslist.Count == 1) 87 | { 88 | Console.WriteLine("Waiting for exit."); 89 | } 90 | else if (waitAny) 91 | { 92 | Console.WriteLine("Waiting for any to exit."); 93 | } 94 | else 95 | { 96 | Console.WriteLine("Waiting for all to exit."); 97 | } 98 | 99 | if (waitAny) 100 | { 101 | var tasks = pslist 102 | .Select(ps => ps.WaitForExitAsync()) 103 | .ToArray(); 104 | 105 | Task.WaitAny(tasks); 106 | } 107 | else 108 | { 109 | foreach (var ps in pslist) 110 | { 111 | ps.WaitForExit(); 112 | } 113 | } 114 | 115 | var psExitCount = 0; 116 | 117 | foreach (var ps in pslist) 118 | { 119 | if (ps.HasExited) 120 | { 121 | psExitCount++; 122 | 123 | Console.WriteLine($"{ps.Id,7} exit"); 124 | } 125 | } 126 | 127 | return psExitCount; 128 | } 129 | catch (Exception ex) 130 | { 131 | Console.ForegroundColor = ConsoleColor.Red; 132 | Console.Error.WriteLine(ex.GetBaseException().Message); 133 | Console.ResetColor(); 134 | 135 | return ex.HResult; 136 | } 137 | finally 138 | { 139 | pslist.ForEach(ps => ps.Dispose()); 140 | } 141 | } 142 | 143 | #if !NET5_0_OR_GREATER 144 | private static Task WaitForExitAsync(this Process ps) 145 | => Task.Run(ps.WaitForExit); 146 | #endif 147 | } -------------------------------------------------------------------------------- /waitps/waitps.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net45;net9.0;net8.0 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /waitwin/Program.cs: -------------------------------------------------------------------------------- 1 | using LTRData.Extensions.CommandLine; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Runtime.InteropServices; 5 | using System.Threading; 6 | using System.Windows.Automation; 7 | 8 | namespace waitwin; 9 | 10 | public static partial class Program 11 | { 12 | #if NET7_0_OR_GREATER 13 | [LibraryImport("user32", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)] 14 | private static partial nint FindWindowW(string? lpClassName, string lpWindowName); 15 | #else 16 | [DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)] 17 | private static extern nint FindWindowW(string? lpClassName, string lpWindowName); 18 | #endif 19 | 20 | public static int Main(params string[] args) 21 | { 22 | var cmds = CommandLineParser.ParseCommandLine(args, StringComparer.Ordinal); 23 | 24 | var waitAny = false; 25 | 26 | string[] windows = []; 27 | 28 | foreach (var cmd in cmds) 29 | { 30 | switch (cmd.Key) 31 | { 32 | case "a": 33 | waitAny = true; 34 | break; 35 | 36 | case "": 37 | windows = cmd.Value; 38 | break; 39 | 40 | default: 41 | Console.WriteLine($@"Window wait utility - Copyright (c) 2025 Olof Lagerkvist, LTR Data 42 | https://ltr-data.se/opencode.html 43 | 44 | Syntax: 45 | 46 | waitwin [-a] winTitle1 [winTitle2 ...] 47 | 48 | -a Wait for any of specified windows to close. Otherwise, waits for all 49 | of specified windows to close. 50 | 51 | Windows can be specified as numeric window handles or window title strings."); 52 | 53 | return -1; 54 | } 55 | } 56 | 57 | var waits = new List(); 58 | 59 | foreach (var window in windows) 60 | { 61 | if (!int.TryParse(window, out var hwnd)) 62 | { 63 | var windowTitle = window; 64 | string? className = null; 65 | var delim = windowTitle.IndexOf('\\'); 66 | if (delim > 0) 67 | { 68 | className = windowTitle.Substring(0, delim); 69 | windowTitle = windowTitle.Substring(delim + 1); 70 | } 71 | 72 | hwnd = (int)FindWindowW(className, windowTitle); 73 | } 74 | 75 | if (hwnd == 0) 76 | { 77 | Console.WriteLine($"Window '{window}' not found."); 78 | continue; 79 | } 80 | 81 | Console.WriteLine($"{hwnd,7} {window}"); 82 | 83 | var element = AutomationElement.FromHandle((nint)hwnd); 84 | 85 | var wait = new ManualResetEvent(initialState: false); 86 | 87 | Automation.AddAutomationEventHandler( 88 | WindowPattern.WindowClosedEvent, 89 | element, 90 | TreeScope.Subtree, 91 | (_, _) => wait.Set()); 92 | 93 | waits.Add(wait); 94 | } 95 | 96 | if (waits.Count == 0) 97 | { 98 | return 0; 99 | } 100 | 101 | if (waits.Count == 1) 102 | { 103 | Console.WriteLine("Waiting for close."); 104 | } 105 | else if (waitAny) 106 | { 107 | Console.WriteLine("Waiting for any to close."); 108 | } 109 | else 110 | { 111 | Console.WriteLine("Waiting for all to close."); 112 | } 113 | 114 | var i = 0; 115 | 116 | if (waitAny) 117 | { 118 | i = WaitHandle.WaitAny([.. waits]); 119 | } 120 | else 121 | { 122 | WaitHandle.WaitAll([.. waits]); 123 | } 124 | 125 | Console.WriteLine("Closed."); 126 | 127 | Automation.RemoveAllEventHandlers(); 128 | 129 | waits.ForEach(wait => wait.Close()); 130 | 131 | return i; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /waitwin/waitwin.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net35;net40;net8.0-windows;net9.0-windows 6 | true 7 | true 8 | enable 9 | true 10 | false 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | --------------------------------------------------------------------------------