Sign in to follow this  
Followers 0
cojms1

String from Pointer

7 posts in this topic

Hi,

I'm workiong on some code to enumerate the services that are running on a machine.

Below is the code I currently have.

Thes structure in question is: -

typedef struct _ENUM_SERVICE_STATUS {
  LPTSTR lpServiceName;
  LPTSTR lpDisplayName;
  SERVICE_STATUS ServiceStatus;
} ENUM_SERVICE_STATUS, 
 *LPENUM_SERVICE_STATUS;

lpServiceName
The name of a service in the service control manager database. The maximum string length is 256 characters. The service control manager database preserves the case of the characters, but service name comparisons are always case insensitive. A slash (/), backslash (\), comma, and space are invalid service name characters.

lpDisplayName
A display name that can be used by service control programs, such as Services in Control Panel, to identify the service. This string has a maximum length of 256 characters. The name is case-preserved in the service control manager. Display name comparisons are always case-insensitive.

The question is which data type do I use to represent LPTSTR?

If I currently have the correct type then how do I retrieve the string from the pointer given?

;*********************************************
; Aim:   To retrieve a list of the services
;*********************************************
Func EnumerateServices($dwServiceType = 0x30, $dwServiceState = 0x3)

   $pagResults = 20
   $lenStruct = 9

   $hndSCM = GetServiceManagerHandle()
   $cbBufSize = 0
   $cbBytesNeeded = DllStructCreate("dword")
   $pcbBytesNeeded = DllStructGetPtr($cbBytesNeeded)
   $ServicesReturned = DllStructCreate("dword")
   $lpServicesReturned = DllStructGetPtr($ServicesReturned)
   $ResumeHandle = DllStructCreate("dword")
   $lpResumeHandle = DllStructGetPtr($ResumeHandle)
   DllStructSetData($lpResumeHandle, 1, 0)
   
   $ret = DllCall("advapi32.dll", "int", "EnumServicesStatus", "int", $hndSCM, "int", $dwServiceType, "int", $dwServiceState, "int", 0, "int", 0, "ptr", $pcbBytesNeeded, "ptr", $lpServicesReturned, "int", 0)
   $ret = DllCall("kernel32.dll", "int", "GetLastError")
   if $ret[0] = $ERROR_MORE_DATA then
      $strEnumServiceStatus = "int;int"
      $strServiceStatus = "dword;dword;dword;dword;dword;dword;dword"
      $_ENUM_SERVICE_STATUS = DllStructCreate($strEnumServiceStatus & ";" & $strServiceStatus)
      $size = DllStructGetSize($_ENUM_SERVICE_STATUS)
      $needed = Round((DllStructGetData($cbBytesNeeded, 1) / $size) + 1)
      $cbBufSize = $pagResults * $size
      $strTemp = _StringRepeat($strEnumServiceStatus & ";" & $strServiceStatus & ";", $pagResults)
      $strTemp = StringTrimRight($strTemp, 1)
      $_ENUM_SERVICE_STATUS = 0
      $_ENUM_SERVICE_STATUS = DllStructCreate($strTemp)
     ;do
         $ret = DllCall("advapi32.dll", "int", "EnumServicesStatus", "int", $hndSCM, "int", $dwServiceType, "int", $dwServiceState, "ptr", DllStructGetPtr($_ENUM_SERVICE_STATUS), "int", $cbBufSize, "ptr", $pcbBytesNeeded, "ptr", $lpServicesReturned, "ptr", $lpResumeHandle)
         $ret = DllCall("kernel32.dll", "int", "GetLastError")
         $numEntries = DllStructGetData($ServicesReturned, 1)
         msgbox(0, "", $numEntries)
         if $numEntries <> 0 then
            for $i = 1 to $numEntries
               $strTemp = ""
               $offset = (($i -1) * $lenStruct)
               $strServiceName = ""
               for $j = 1 to $lenStruct
                  $strTemp &= DllStructGetData($_ENUM_SERVICE_STATUS, $offset + $j) & @crlf
               next
               msgbox(0, "", $strTemp)
            next 
         endif
     ;until $ret[0] <> $ERROR_MORE_DATA
   endif
   $_ENUM_SERVICE_STATUS = 0
   CloseServiceHandle($hndSCM)

EndFunc

Any help appreciated.

Share this post


Link to post
Share on other sites



It states that it's a string(for the first), which would be a 'char' type. It also states that it has a maximum of 256 characters, so I'd try making the type 'char[257]'. That should also tell you what you should do with the 2nd. :D

Nomad


Share this post


Link to post
Share on other sites

Am I missing something? Doesn't the basic DllCall() type "str" do this? Rule number one of using DllCall() is don't over-complicate it by using DllStruct stuff when DllCall() can do it natively.

Share this post


Link to post
Share on other sites

i think you are missing this:

typedef struct _ENUM_SERVICE_STATUS {

LPTSTR lpServiceName;

LPTSTR lpDisplayName;

SERVICE_STATUS ServiceStatus;

} ENUM_SERVICE_STATUS,

*LPENUM_SERVICE_STATUS;


My UDF's:;mem stuff_Mem;ftp stuff_FTP ( OLD );inet stuff_INetGetSource ( OLD )_INetGetImage _INetBrowse ( Collection )_EncodeUrl_NetStat_Google;random stuff_iPixelSearch_DiceRoll

Share this post


Link to post
Share on other sites

Ahhh, it's part of a structure. My second comment still stands. I see a couple places where a DWORD is created. A DWORD is the same size of an int so that's just redundant (Remember, int_ptr, too).

Share this post


Link to post
Share on other sites

Here's a link to the call definition on MSDN.

BOOL WINAPI EnumServicesStatus(
  SC_HANDLE hSCManager,
  DWORD dwServiceType,
  DWORD dwServiceState,
  LPENUM_SERVICE_STATUS lpServices,
  DWORD cbBufSize,
  LPDWORD pcbBytesNeeded,
  LPDWORD lpServicesReturned,
  LPDWORD lpResumeHandle
);

typedef struct _ENUM_SERVICE_STATUS {
  LPTSTR lpServiceName;
  LPTSTR lpDisplayName;
  SERVICE_STATUS ServiceStatus;
} ENUM_SERVICE_STATUS, 
 *LPENUM_SERVICE_STATUS;

It says that lpServices is a point to an array of ENUM_SERVICE_STATUS.

From what I can gather I would define ENUM_SERVICE_STATUS and then use DllStructGetPtr to get the pointer to that structure. How do I create an array of that structure? I do not now how many services will be returned, even after the 1st call that is being used to get the size of the buffer required.

If I assign lpServiceName and lpDisplayName as char[257] then the size of the structure cannot be used to to determine the size of the array required.

I am working from VB source which can be found here

Any help is greatly appreciated.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0