Solved

EnumServicesStatus Vs. EnumServicesStatusEx

Posted on 2004-09-03
7
1,245 Views
Last Modified: 2008-01-09
I've a problem when using either EnumServicesStatus or EnumServicesStatusEx.

When using EnumServicesStatus it returns 85 services.

When using EnumServicesStatusEx it returns only 70 services (and no, i haven't deleted any services). I noticed that the Alerter service is showing up when using EnumServicesStatus but not when i'm using EnumServicesStatusEx.

All the parameteres are the same:
SC_ENUM_TYPE       InfoLevel = SC_ENUM_PROCESS_INFO;
DWORD            dwServiceType = SERVICE_WIN32,
            dwServiceState = SERVICE_STATE_ALL,
                      chBufSize = 30720,
            dwServicesReturned,
            dwBytesNeeded,
            dwResumeHandle = 0,
            dwProcID;
LPCTSTR                  pszGroupName = NULL;
LPENUM_SERVICE_STATUS_PROCESS lpServices;

Any1 got any explanations?
0
Comment
Question by:jead99
  • 4
7 Comments
 
LVL 11

Expert Comment

by:KurtVon
Comment Utility
Check and make sure GetLastError isn't returning ERROR_MORE_DATA.  The current size is about 384 bytes each for 80 items and 438 bytes each for 70.  I know the Ex version returns bigger structs, but only 16 bytes or so.  Still worth checking out though.

Note that the Ex version returns ERROR_MORE_DATA but the original returns ERROR_INSUFFICIENT_BUFFER, so if you are catching the error already, make sure you are checking for the correct one.

Hope this helps.
0
 

Author Comment

by:jead99
Comment Utility
Allready tried that, it doesn't return any errors.
0
 
LVL 11

Expert Comment

by:KurtVon
Comment Utility
Keep in mind that if there is more data the function call doesn't return an error.  You still have to check the GetLastError() value.  Dumb, I know, but the logic seems to be that since the function returns as much data as can fit in the buffer you provided it did succeed, even if there was an "error" of the buffer being too small.
0
 
LVL 11

Expert Comment

by:KurtVon
Comment Utility
By the way, I tried running this code as a test:

    ENUM_SERVICE_STATUS Services[100];
    DWORD cbNeeded, dwRet, dwHandle = 0;
    SC_HANDLE hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
    EnumServicesStatus(hSC, SERVICE_WIN32, SERVICE_STATE_ALL,
                       Services, sizeof(Services), &cbNeeded,
                       &dwRet, &dwHandle);


    dwHandle = 0;
    ENUM_SERVICE_STATUS_PROCESS ServicesEx[100];
    EnumServicesStatusEx(hSC, SC_ENUM_PROCESS_INFO, SERVICE_WIN32,
                         SERVICE_STATE_ALL, (BYTE*)ServicesEx, sizeof(ServicesEx),
                         &cbNeeded, &dwRet, &dwHandle,
                         NULL);

and despite there being more than enough entries, both required multiple calls to feed through the entire services set, even though there was plenty of room in the array.  In the end they returned the same number of services, though.

I'm surprised about the alerter service.  It showed up first on both lists for me.
0
 
LVL 11

Accepted Solution

by:
KurtVon earned 50 total points
Comment Utility
This code worked perfectly (the first looped 3 times, the second twice):

    ENUM_SERVICE_STATUS Services[100];
    DWORD dwIndex = 0;
    DWORD cbNeeded, dwRet, dwHandle = 0;
    SC_HANDLE hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
    do
    {
        EnumServicesStatus(hSC, SERVICE_WIN32, SERVICE_STATE_ALL,
                           &(Services[dwIndex]), sizeof(Services[0]) * (100 - dwIndex), &cbNeeded,
                           &dwRet, &dwHandle);
        dwIndex += dwRet;
    } while ((dwHandle != 0) && (dwIndex < 100));


    dwHandle = 0;
    dwIndex = 0;
    ENUM_SERVICE_STATUS_PROCESS ServicesEx[100];
    do
    {
        EnumServicesStatusEx(hSC, SC_ENUM_PROCESS_INFO, SERVICE_WIN32,
                             SERVICE_STATE_ALL, (BYTE*)&(ServicesEx[dwIndex]),
                             sizeof(ServicesEx[0]) * (100 - dwIndex),
                             &cbNeeded, &dwRet, &dwHandle,
                             NULL);
        dwIndex += dwRet;
    } while ((dwHandle != 0) && (dwIndex < 100));
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now