├── .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 |
60 | Public Property Datasource() As String
61 | Get
62 | Return CType(Me("Datasource"), String)
63 | End Get
64 | Set
65 | Me("Datasource") = Value
66 | End Set
67 | End Property
68 |
69 |
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 |
--------------------------------------------------------------------------------