Get description of window service?

Everything else that doesn't fall into one of the other PB categories.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Get description of window service?

Post by Joakim Christiansen »

Okay, so I'm enumerating the Windows Services available on the system and I get their description key from the registry which gives me data like this:

Code: Select all

@%SystemRoot%\system32\wcncsvc.dll,-4
@%SystemRoot%\system32\WcsPlugInService.dll,-201
@%systemroot%\system32\wdi.dll,-503
@%systemroot%\system32\wdi.dll,-501
@%systemroot%\system32\webclnt.dll,-101
@%SystemRoot%\system32\wecsvc.dll,-201
So how do I use these to get the actual description of the service?
I like logic, hence I dislike humans but love computers.
User avatar
tinman
PureBasic Expert
PureBasic Expert
Posts: 1102
Joined: Sat Apr 26, 2003 4:56 pm
Location: Level 5 of Robot Hell
Contact:

Post by tinman »

Why not use EnumServicesStatus_() which looks like it will give you a proper description (as well as a lot of other stuff)?
If you paint your butt blue and glue the hole shut you just themed your ass but lost the functionality.
(WinXPhSP3 PB5.20b14)
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

That is exactly what I do use to enumerate them, but it gives me no description of the service.
Neither does QueryServiceConfig_(), so that's kinda why I'm asking.
I like logic, hence I dislike humans but love computers.
User avatar
tinman
PureBasic Expert
PureBasic Expert
Posts: 1102
Joined: Sat Apr 26, 2003 4:56 pm
Location: Level 5 of Robot Hell
Contact:

Post by tinman »

Edit: I've removed the code because it was only listing the names not the descriptions. Doh.

Enumerate the services as you are doing now. Then for each one use OpenService to open it, then use QueryServiceConfig2_() (with info level 1) to get the description.
Last edited by tinman on Fri Aug 10, 2007 12:20 pm, edited 1 time in total.
If you paint your butt blue and glue the hole shut you just themed your ass but lost the functionality.
(WinXPhSP3 PB5.20b14)
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

I try to use QueryServiceConfig2 to see if I can get any description, but I have problems importing it and using it properly. :?
I like logic, hence I dislike humans but love computers.
SunSatION
User
User
Posts: 85
Joined: Tue Jun 21, 2005 7:26 pm
Location: Malta

Post by SunSatION »

Can't you list them from the registry?

Code: Select all

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services
To add a description to a new service, you need to write a reg entry, so i guess to read it, you need to read a registry entry
User avatar
tinman
PureBasic Expert
PureBasic Expert
Posts: 1102
Joined: Sat Apr 26, 2003 4:56 pm
Location: Level 5 of Robot Hell
Contact:

Post by tinman »

Try this, seems to work for me. As for your original question about the DLL names and -numbers, you could try using LoadString_() to load the specified -(string number) from the DLL.

Code: Select all

#SERVICE_WIN32_OWN_PROCESS      = $00000010
#SERVICE_WIN32_SHARE_PROCESS    = $00000020
#SERVICE_WIN32                  = #SERVICE_WIN32_OWN_PROCESS | #SERVICE_WIN32_SHARE_PROCESS

Structure SERVICE_DESCRIPTION
    *lpDescription.c
EndStructure

Import "C:\Program Files\Microsoft SDKs\Windows\v6.0\Lib\Advapi32.lib"
    QueryServiceConfig2_.l(hService.l, dwInfoLevel.l, lpBuffer.l, cbBufSize.l, pcbBytesNeeded.l) As "_QueryServiceConfig2A@20"
EndImport

Define.l hSCM
Define.l dwError
Define.l success
service_data_size.l = 65536
Dim service_data.b(service_data_size)

Structure ptrENUM_SERVICE_STATUS
    ess.ENUM_SERVICE_STATUS[0]
EndStructure

*service_info.ptrENUM_SERVICE_STATUS = @service_data(0)
Define.l dwBytesNeeded
Define.l dwNumberServices
dwResumeHandle.l = 0

description_data_size = 8192
Dim description_data.b(description_data_size)
*description.SERVICE_DESCRIPTION = @description_data(0)

hSCM.l = OpenSCManager_(0, 0, #GENERIC_READ)
If hSCM
    Repeat
        success.l = EnumServicesStatus_(hSCM, #SERVICE_WIN32, #SERVICE_ACTIVE, *service_info, service_data_size, @dwBytesNeeded, @dwNumberServices, @dwResumeHandle)
        dwError.l = GetLastError_()
        
        If success<>0 Or (success=0 And #ERROR_MORE_DATA = dwError)
            For i.l = 0 To dwNumberServices-1
                Debug PeekS(*service_info\ess[i]\lpDisplayName)
                
                hService.l = OpenService_(hSCM, *service_info\ess[i]\lpServiceName, #GENERIC_READ)
                If hService
                    success = QueryServiceConfig2_(hService, #SERVICE_CONFIG_DESCRIPTION, *description, description_data_size, @dwBytesNeeded)
                    ;Debug Str(success)
                    If success
                        ;Debug Str(*description)
                        If *description\lpDescription
                            Debug PeekS(*description\lpDescription)
                        Else
                            Debug "No description"
                        EndIf
                    Else
                        Debug Str(GetLastError_())
                    EndIf
                    CloseServiceHandle_(hService)
                EndIf
            Next
        EndIf
    Until #ERROR_MORE_DATA <> dwError

    CloseServiceHandle_(hSCM)
EndIf
If you paint your butt blue and glue the hole shut you just themed your ass but lost the functionality.
(WinXPhSP3 PB5.20b14)
User avatar
tinman
PureBasic Expert
PureBasic Expert
Posts: 1102
Joined: Sat Apr 26, 2003 4:56 pm
Location: Level 5 of Robot Hell
Contact:

Post by tinman »

You could try this for the @whatever strings. I can't test this, according to the MSDN localised strings only appeared in Vista which I don't have.

Code: Select all


service_description.s = "@%systemroot%\system32\webclnt.dll,-101"

If Left(service_description, 1)="@"
    comma_pos.l = FindString(service_description, ",", 0)
    service_desc_dll_name.s = Mid(service_description, 2, comma_pos - 2)
    service_desc_str_id.l = Val(Mid(service_description, comma_pos+1, Len(service_description) - comma_pos))

    full_path_length.l = ExpandEnvironmentStrings_(@service_desc_dll_name, 0, 0)
    If full_path_length>0
        full_path.s = Space(full_path_length)
        If ExpandEnvironmentStrings_(@service_desc_dll_name, @full_path, full_path_length)
            hModule = LoadLibrary_(full_path)
            If hModule
                description.s = Space(256)
                Debug @description
                string_length.l = LoadString_(hModule, -service_desc_str_id, @description, 256)
                If string_length > 256
                    description.s = Space(string_length)
                    LoadString_(hModule, -service_desc_str_id, @description, string_length)
                EndIf
                
                If string_length > 0
                    Debug PeekS(@description)
                EndIf

                FreeLibrary_(hModule)
            EndIf
        EndIf
    EndIf
EndIf
If you paint your butt blue and glue the hole shut you just themed your ass but lost the functionality.
(WinXPhSP3 PB5.20b14)
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

tinman wrote:Try this, seems to work for me.
I really appreciate your help, but sadly this code gives me a fatal error :S
I tried with PB 4.02 and both the latest beta versions, but I'm using Vista, maybe that's it.

And the code right over this post works very fine! :D
But I want support for XP too so can't use it I guess, or maybe (I'll try on XP later).
I like logic, hence I dislike humans but love computers.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Image
Anyone know why this happens?
I like logic, hence I dislike humans but love computers.
Hi-Toro
Enthusiast
Enthusiast
Posts: 269
Joined: Sat Apr 26, 2003 3:23 pm

Post by Hi-Toro »

Here's the Registry method... for NT-based Windows only (tested only on XP):

Code: Select all


; -----------------------------------------------------------------------------
; TURN DEBUGGER ON TO SEE THE OUTPUT!!!
; -----------------------------------------------------------------------------

; Just call GetServiceList () and then iterate through the list (see
; demo at bottom of source)...

; -----------------------------------------------------------------------------
; Required list...
; -----------------------------------------------------------------------------

Structure ServiceList
    displayname.s
    description.s
EndStructure

Global NewList ServiceList.ServiceList ()

; -----------------------------------------------------------------------------
; Registry support functions...
; -----------------------------------------------------------------------------

Procedure OpenKey (openkey, subkey$, flags)
    result = RegOpenKeyEx_ (openkey, subkey$, 0, flags, @handle)
    If result = #ERROR_SUCCESS
        ProcedureReturn handle
    EndIf
EndProcedure

Procedure CloseKey (openkey)
    ProcedureReturn RegCloseKey_ (openkey)
EndProcedure

Procedure.s GetStringValue (openkey, value$)
    buffer$ = Space (1024)
    size.l = 1024
    res = RegQueryValueEx_ (openkey, @value$, #Null, @type, @buffer$, @size)
    If res <> #ERROR_SUCCESS
        buffer$ = ""
    EndIf
    ProcedureReturn buffer$
EndProcedure

Procedure GetIntValue (openkey, value$)
    size = 4
    RegQueryValueEx_ (openkey, @value$, #Null, @type, @res, @size)
    ProcedureReturn res
EndProcedure

; -----------------------------------------------------------------------------
; Specific to listing services...
; -----------------------------------------------------------------------------

Procedure EnumServices (openkey)

    buffsize = 256
    buffer$ = Space (buffsize)
    result = RegEnumKeyEx_ (openkey, index, @buffer$, @buffsize, #Null, #Null, #Null, @written.SYSTEMTIME)
    
    index = index + 1
    
    If result = #ERROR_SUCCESS
    
        Repeat
        
                buffsize = 256
                buffer$ = Space (buffsize)
                result = RegEnumKeyEx_ (openkey, index, @buffer$, @buffsize, #Null, #Null, #Null, @written.SYSTEMTIME)
                
                If result = #ERROR_SUCCESS
                    
                    key = OpenKey (openkey, buffer$, #KEY_ALL_ACCESS)
                    If key
                    
                        servicetype = GetIntValue (key, "Type")
                        
                        ; Retrieve only those listed in Control Panel -> Admin Tools -> Services...
                        
                        If servicetype > 8 ; See http://www.jsifaq.com/SF/Tips/Tip.aspx?id=0324
                        
                            AddElement (ServiceList ())
                            
                            dsp$ = GetStringValue (key, "DisplayName")
                            dsc$ = GetStringValue (key, "Description")
                            
                            If dsp$ = ""
                                dsp$ = "Unknown service"
                            EndIf
                            
                            If dsc$ = ""
                                dsc$ = "[No description]"
                            EndIf
                            
                            ServiceList ()\displayname = dsp$
                            ServiceList ()\description = dsc$
                            
                        EndIf
                        
                        CloseKey (key)
                        
                    EndIf
                    
                EndIf
                
                index = index + 1
                
        Until result = #ERROR_NO_MORE_ITEMS
        
    EndIf
    
EndProcedure

; -----------------------------------------------------------------------------
; Easy wrapper function...
; -----------------------------------------------------------------------------

Procedure GetServiceList ()
    ClearList (ServiceList ())
    services = OpenKey (#HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services", #KEY_ALL_ACCESS)
    If services
        EnumServices (services)
        CloseKey (services)
    EndIf
    ResetList (ServiceList ())
EndProcedure

; -----------------------------------------------------------------------------
; D E M O . . .
; -----------------------------------------------------------------------------
 
GetServiceList ()
 
While NextElement (ServiceList ())
        Debug ServiceList ()\displayname
        Debug Chr (34) + ServiceList ()\description + Chr (34)
        Debug ""
Wend
James Boyd
http://www.hi-toro.com/
Death to the Pixies!
User avatar
tinman
PureBasic Expert
PureBasic Expert
Posts: 1102
Joined: Sat Apr 26, 2003 4:56 pm
Location: Level 5 of Robot Hell
Contact:

Post by tinman »

Joakim Christiansen wrote:
tinman wrote:Try this, seems to work for me.
I really appreciate your help, but sadly this code gives me a fatal error :S
I tried with PB 4.02 and both the latest beta versions, but I'm using Vista, maybe that's it.
There are quite a few places in the code where pointer values are not checked. Perhaps if your config has no description or display name then the pointers will be NULL and my code doesn't catch that.
And the code right over this post works very fine! :D
But I want support for XP too so can't use it I guess, or maybe (I'll try on XP later).
If you can get the original code working (that enumerates and gets the description) then you can use that on XP. If you also add the code that checks for "@" at the start of the description then it should work for XP and Vista.

For the linker error check the following:
  • Path to .lib file is correct in the import statement - I hardcoded it to the default English language location for the Vista platform SDK. As you said before, the PB libs do not come with that function included.
  • Try using "_QueryServiceConfig2A@20" in the import line if that doesn't work
  • Try changing it to _QueryServiceConfig2W if you are using Unicode.
  • I had another thing to try but I forgot.
If you paint your butt blue and glue the hole shut you just themed your ass but lost the functionality.
(WinXPhSP3 PB5.20b14)
Post Reply