@@ -3,6 +3,7 @@ Imports System.IO
33Imports Microsoft.Win32
44Imports System.Runtime.InteropServices
55Imports System.Text
6+ Imports System.Text.RegularExpressions
67
78Module WindowsServiceHelper
89
@@ -220,6 +221,48 @@ Module WindowsServiceHelper
220221 End If
221222 End Function
222223
224+ Private Function ParseInfLine(line As String ) As Tuple( Of String , String )
225+ Dim noComment = line.Split( ";"c )( 0 ).Trim()
226+ Dim parts = noComment.Split( ","c )
227+
228+ If parts.Length < 2 Then
229+ Return Nothing
230+ End If
231+
232+ Dim infFile = parts( 0 ).Trim().TrimStart( "@"c )
233+ Dim token = parts( 1 ).Trim()
234+
235+ Return Tuple.Create(infFile, token)
236+ End Function
237+
238+ Private Function ResolveInfToken(infPath As String , token As String ) As String
239+ Try
240+ Dim key As String = token.Trim( "%"c )
241+
242+ Dim lines As String () = File.ReadAllLines(infPath)
243+ Dim inStrings As Boolean = False
244+ For Each line In lines
245+ Dim lineTrim As String = line.Trim()
246+ If lineTrim.StartsWith( "[Strings]" , StringComparison.OrdinalIgnoreCase) Then
247+ inStrings = True
248+ Continue For
249+ End If
250+
251+ If inStrings Then
252+ If lineTrim.StartsWith( "[" ) Then Exit For
253+
254+ Dim match = Regex.Match(lineTrim, "^(?<k>[^\s=]+)\s*=\s*""?(?<v>[^""]+)""?$" )
255+ If match.Success AndAlso match.Groups( "k" ).Value.Equals( key , StringComparison.OrdinalIgnoreCase) Then
256+ Return match.Groups( "v" ).Value
257+ End If
258+ End If
259+ Next
260+ Catch ex As Exception
261+
262+ End Try
263+ Return ""
264+ End Function
265+
223266 Function GetServiceList(MountPath As String ) As List( Of WindowsService)
224267 ' For the required privileges a service may have, we have to fill in the constants first so that we don't have things like
225268 ' "SeUndockPrivilege", "SeShutdownPrivilege"; but rather "Remove computer from docking station", and so on... we want the
@@ -265,13 +308,19 @@ Module WindowsServiceHelper
265308 ' This "service" is bogus
266309 Continue For
267310 End If
268- ' TODO: for devices, tweak the indirect string resolver to like INF files
269- ' TODO: failure/recovery actions need to be implemented, which will require us to understand binary data
270- ' TODO: relationships with services a service depends on or services that depend on a service need to be implemented
271311
272312 serviceEntryName = ServiceName
273313 serviceDisplayName = ServiceInfoRk.GetValue( "DisplayName" , "" )
274- If serviceDisplayName.StartsWith( "@" ) Then
314+ If serviceDisplayName.StartsWith( "@" ) AndAlso serviceDisplayName.ToLowerInvariant().Contains( ".inf" ) Then
315+ Dim parsedInf As Tuple( Of String , String ) = ParseInfLine(serviceDisplayName)
316+
317+ If parsedInf IsNot Nothing Then
318+ Dim resolvedString As String = ResolveInfToken(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "INF" , parsedInf.Item1), parsedInf.Item2)
319+ If Not String .IsNullOrEmpty(resolvedString) Then
320+ serviceDisplayName = resolvedString
321+ End If
322+ End If
323+ ElseIf serviceDisplayName.StartsWith( "@" ) Then
275324 serviceDisplayName = ResolveIndirectString(serviceDisplayName)
276325 End If
277326 serviceDescription = ServiceInfoRk.GetValue( "Description" , "" )
0 commit comments