Skip to content

Commit fdbea9b

Browse files
committed
[ServiceManager] Add basic device/service lister
The system device/service manager interface is in EXTREMELY EARLY stages and will only list the results obtained. No management actions have been implemented yet. There are also several bugs in the manager that need to be fixed, and the overall manager UI also needs to adapt to the color schemes. Regardless, this is the INTRODUCTION of a new thing.
1 parent 8a05381 commit fdbea9b

File tree

9 files changed

+390
-10
lines changed

9 files changed

+390
-10
lines changed

DISMTools.vbproj

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,12 @@
674674
<Compile Include="Panels\Img_Ops\Registry\RegistryControlPanel.vb">
675675
<SubType>Form</SubType>
676676
</Compile>
677+
<Compile Include="Panels\Img_Ops\Services\ServiceManagementForm.Designer.vb">
678+
<DependentUpon>ServiceManagementForm.vb</DependentUpon>
679+
</Compile>
680+
<Compile Include="Panels\Img_Ops\Services\ServiceManagementForm.vb">
681+
<SubType>Form</SubType>
682+
</Compile>
677683
<Compile Include="Panels\Img_Ops\Switch\ImgIndexSwitch.Designer.vb">
678684
<DependentUpon>ImgIndexSwitch.vb</DependentUpon>
679685
</Compile>
@@ -1083,6 +1089,9 @@
10831089
<EmbeddedResource Include="Panels\Img_Ops\Registry\RegistryControlPanel.resx">
10841090
<DependentUpon>RegistryControlPanel.vb</DependentUpon>
10851091
</EmbeddedResource>
1092+
<EmbeddedResource Include="Panels\Img_Ops\Services\ServiceManagementForm.resx">
1093+
<DependentUpon>ServiceManagementForm.vb</DependentUpon>
1094+
</EmbeddedResource>
10861095
<EmbeddedResource Include="Panels\Img_Ops\Switch\ImgIndexSwitch.resx">
10871096
<DependentUpon>ImgIndexSwitch.vb</DependentUpon>
10881097
</EmbeddedResource>

Elements/ServiceManagement/WindowsService.vb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Public Class WindowsService
22

3-
Enum ServiceStartType
3+
Enum ServiceStartType As Integer
44
Unknown = -1
55
BootLoader = 0
66
IOSystem = 1
@@ -9,7 +9,7 @@
99
Disabled = 4
1010
End Enum
1111

12-
Enum ServiceType
12+
Enum ServiceType As Integer
1313
Unknown = -1
1414
KernelDeviceDriver = 1
1515
FileSystemDriver = 2
@@ -18,7 +18,7 @@
1818
WindowsService = 32
1919
End Enum
2020

21-
Enum ServiceErrorControl
21+
Enum ServiceErrorControl As Integer
2222
Unknown = -1
2323
Ignore = 0
2424
Normal = 1
@@ -27,20 +27,24 @@
2727
End Enum
2828

2929
Public Property Name As String
30+
Public Property DisplayName As String
3031
Public Property Description As String
3132
Public Property ObjectName As String
3233
Public Property ImagePath As String
3334
Public Property StartType As ServiceStartType
35+
Public Property DelayedStart As Boolean
3436
Public Property Type As ServiceType
3537
Public Property ErrorControl As ServiceErrorControl
3638
Public Property RequiredPrivileges As New List(Of NTSecurityPrivilegeConstant)
3739

38-
Public Sub New(name As String, description As String, objectName As String, imagePath As String, startType As ServiceStartType, type As ServiceType, errorControl As ServiceErrorControl, ntPrivileges As List(Of NTSecurityPrivilegeConstant))
40+
Public Sub New(name As String, displayName As String, description As String, objectName As String, imagePath As String, startType As ServiceStartType, delayedStart As Boolean, type As ServiceType, errorControl As ServiceErrorControl, ntPrivileges As List(Of NTSecurityPrivilegeConstant))
3941
Me.Name = name
42+
Me.DisplayName = displayName
4043
Me.Description = description
4144
Me.ObjectName = objectName
4245
Me.ImagePath = imagePath
4346
Me.StartType = startType
47+
Me.DelayedStart = delayedStart
4448
Me.Type = type
4549
Me.ErrorControl = errorControl
4650
Me.RequiredPrivileges = ntPrivileges

Elements/ServiceManagement/WindowsServiceHelper.vb

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
Imports Microsoft.VisualBasic.ControlChars
2+
Imports System.IO
3+
Imports Microsoft.Win32
24

35
Module WindowsServiceHelper
46

57
Private PrivilegeConstantDictionary As New Dictionary(Of String, NTSecurityPrivilegeConstant)
68
Private PrivilegeMappingDictionary As New Dictionary(Of String, String)
79

810
Sub FillInConstants()
11+
PrivilegeConstantDictionary.Clear()
12+
PrivilegeMappingDictionary.Clear()
913
PrivilegeConstantDictionary.Add("SE_ASSIGNPRIMARYTOKEN_NAME",
1014
New NTSecurityPrivilegeConstant(
1115
"SeAssignPrimaryTokenPrivilege",
@@ -193,4 +197,101 @@ Module WindowsServiceHelper
193197
Next
194198
End Sub
195199

200+
Function GetServiceList(MountPath As String) As List(Of WindowsService)
201+
' For the required privileges a service may have, we have to fill in the constants first so that we don't have things like
202+
' "SeUndockPrivilege", "SeShutdownPrivilege"; but rather "Remove computer from docking station", and so on... we want the
203+
' friendly things.
204+
FillInConstants()
205+
Dim serviceList As New List(Of WindowsService)
206+
207+
' Time to load up a registry hive
208+
If RegistryHelper.LoadRegistryHive(Path.Combine(MountPath, "Windows", "system32", "config", "SYSTEM"), "HKLM\zSYS") = 0 Then
209+
Try
210+
' First we need to grab the default control set of the target image
211+
Dim DefaultControlSet As Integer = RegistryHelper.GetDefaultControlSet("zSYS")
212+
If DefaultControlSet = -1 Then
213+
Throw New Exception("Registry control set could not be obtained")
214+
End If
215+
' We only document a maximum of 999 control sets. CurrentControlSet is not a thing in an offline system, as the registry
216+
' subsystems guess the control set to use based on values in HKLM\SYSTEM\Select.
217+
Dim ServiceRk As RegistryKey = Registry.LocalMachine.OpenSubKey(String.Format("zSYS\ControlSet{0}\Services", DefaultControlSet.ToString().PadLeft(3, "0")), False)
218+
' For some stupid reason, .NET keys are stored in HKLM\SYSTEM\ControlSet<nnn>\Services. GUID keys are also not allowed
219+
Dim ServiceNames() As String = ServiceRk.GetSubKeyNames().Where(Function(serviceName) Not serviceName.StartsWith(".NET", StringComparison.OrdinalIgnoreCase) AndAlso Not serviceName.StartsWith("{")).ToArray()
220+
ServiceRk.Close()
221+
222+
' Now we have to grab as much information as we can
223+
For Each ServiceName In ServiceNames
224+
Dim serviceImagePath As String = "",
225+
serviceEntryName As String = "",
226+
serviceDisplayName As String = "",
227+
serviceDescription As String = "",
228+
serviceObjectName As String = "",
229+
serviceStartType As WindowsService.ServiceStartType = WindowsService.ServiceStartType.Unknown,
230+
serviceDelayedStart As Boolean = False,
231+
serviceType As WindowsService.ServiceType = WindowsService.ServiceType.Unknown,
232+
serviceErrorControl As WindowsService.ServiceErrorControl = WindowsService.ServiceErrorControl.Unknown,
233+
serviceRequiredPrivilegesString() As String = New String() {}
234+
Using ServiceInfoRk As RegistryKey = Registry.LocalMachine.OpenSubKey(String.Format("zSYS\ControlSet{0}\Services\{1}", DefaultControlSet.ToString().PadLeft(3, "0"), ServiceName), False)
235+
serviceImagePath = ServiceInfoRk.GetValue("ImagePath", "", RegistryValueOptions.DoNotExpandEnvironmentNames)
236+
If serviceImagePath = "" Then
237+
' This "service" is bogus
238+
Continue For
239+
End If
240+
' TODO: display names and descriptions can also be pulled from resources that are embedded in executables or libraries.
241+
' TODO: failure/recovery actions need to be implemented, which will require us to understand binary data
242+
' TODO: relationships with services a service depends on or services that depend on a service need to be implemented
243+
244+
serviceEntryName = ServiceName
245+
246+
' We explicitly tell that we want to grab the raw data without env var expansion because REG_EXPAND_SZ values
247+
' are still string values, but with unexpanded environment variables. If the variable exists in the target system,
248+
' it will show that value. This is true FOR THE IMAGE PATH, but we'll also do it for the display name and the description,
249+
' just in case.
250+
serviceDisplayName = ServiceInfoRk.GetValue("DisplayName", "", RegistryValueOptions.DoNotExpandEnvironmentNames)
251+
serviceDescription = ServiceInfoRk.GetValue("Description", "", RegistryValueOptions.DoNotExpandEnvironmentNames)
252+
serviceObjectName = ServiceInfoRk.GetValue("ObjectName", "")
253+
serviceStartType = ServiceInfoRk.GetValue("Start", -1)
254+
serviceDelayedStart = (ServiceInfoRk.GetValue("DelayedAutoStart", 0) = 1)
255+
serviceType = ServiceInfoRk.GetValue("Type", -1)
256+
serviceErrorControl = ServiceInfoRk.GetValue("ErrorControl", -1)
257+
' The required privileges property is a multi-value registry value, so we need an array
258+
serviceRequiredPrivilegesString = ServiceInfoRk.GetValue("RequiredPrivileges", New String() {})
259+
260+
Dim serviceRequiredPrivilegeList As New List(Of NTSecurityPrivilegeConstant)
261+
262+
If serviceRequiredPrivilegesString.Count > 0 Then
263+
' Parse the items themselves to keys that are available in the dictionary we filled
264+
' stuff in
265+
For Each serviceRequiredPrivilegeString In serviceRequiredPrivilegesString
266+
If PrivilegeMappingDictionary.Keys.Contains(serviceRequiredPrivilegeString) Then
267+
' Then add it
268+
Dim constantInHeader As String = PrivilegeMappingDictionary(serviceRequiredPrivilegeString)
269+
serviceRequiredPrivilegeList.Add(PrivilegeConstantDictionary(constantInHeader))
270+
End If
271+
Next
272+
End If
273+
274+
serviceList.Add(New WindowsService(serviceEntryName,
275+
serviceDisplayName,
276+
serviceDescription,
277+
serviceObjectName,
278+
serviceImagePath,
279+
serviceStartType,
280+
serviceDelayedStart,
281+
serviceType,
282+
serviceErrorControl,
283+
serviceRequiredPrivilegeList))
284+
End Using
285+
Next
286+
Catch ex As Exception
287+
288+
End Try
289+
290+
' Now we unload that hive
291+
RegistryHelper.UnloadRegistryHive("HKLM\zSYS")
292+
End If
293+
294+
Return serviceList
295+
End Function
296+
196297
End Module

MainForm.Designer.vb

Lines changed: 14 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

MainForm.vb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16794,4 +16794,8 @@ Public Class MainForm
1679416794
Quote & Path.Combine(Application.StartupPath, "logs", "DT_DynaLog.log") & Quote)
1679516795
End If
1679616796
End Sub
16797+
16798+
Private Sub ManageSystemServicesToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ManageSystemServicesToolStripMenuItem.Click
16799+
ServiceManagementForm.Show()
16800+
End Sub
1679716801
End Class

0 commit comments

Comments
 (0)