queryserviceconfig question

Does anyone have a working code sample of how to use queryserviceconfig in delphi 4?
mantra246Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

BedouinDNCommented:
A bit quick and dirty but...

You will need to add WinSvc.pas into uses clause.
And also will need to do some error trapping (not to mention freeing the memory)

//-----------------------------------QueryServiceConfig------------------------------------------------------

procedure TForm1.QuerySvcConfig(Service: String);
var
schm,
schs: SC_Handle;
ss: TServiceStatus;
dwChkP: DWord;
sConfig: PQueryServiceConfigA;
sNeeded: Cardinal;
begin
schm := OpenSCManager(nil, nil, SC_MANAGER_CONNECT);
        if (schm > 0) then
        begin
        schs := OpenService(schm, PChar(Service), SERVICE_QUERY_CONFIG);
                if (schs > 0) then
                begin
                //Call the QueryServiceConfig function to get the required buffer size
                        if QueryServiceConfig(schs,sConfig,0,sNeeded) <> TRUE then
                        begin
                                if GetLastError = ERROR_INSUFFICIENT_BUFFER then
                                begin
                                //Get the memory required by using the Bytes needed var
                                GetMem(sConfig,sNeeded);
                                        if QueryServiceConfig(schs,sConfig,sNeeded,sNeeded) <> TRUE then
                                        begin
                                        MessageDlg(SysErrorMessage(GetLastError),mtError,[MBOK],0);
                                        end
                                        else
                                        begin
                                        //Play with Config Info here
                                        end;
                                end;
                        end;
                CloseServiceHandle(schs);
                end;
        CloseServiceHandle(schm);
        end;
end;

//----------------------------------------------------------------
0
mantra246Author Commented:
Thanks BedouinDN but i get the error of "Type of actual and formal var parameters must be identical" on both:

if QueryServiceConfig(schs,sConfig,0,sNeeded) <> TRUE

and

if QueryServiceConfig(schs,sConfig,sNeeded,sNeeded) <> TRUE

It seems to be with the sConfig section.

Any idea why and what to do to fix it?

If it can be fixed and it works then it looks like the points are yours - along with a grade A for your help.

0
BedouinDNCommented:
This compiles OK in D6, maybe D4 is looking for a pointer rather than declaring as PQueryServiceConfigA.

Also might be looking for lpServiceConfig instead of PQueryServiceConfigA as this is what MSDN says, so if the below code does not work, try declaring sConfig as lpServiceConfig rather than pointer and remove the reference to PQueryServiceConfigA.
Sorry, I don't have D4 to test with so please let me know how you go..

procedure TForm1.QuerySvcConfig(Service: String);
var
schm,
schs: SC_Handle;
sConfig: Pointer;
pConfig: PQueryServiceConfigA;
sNeeded: Cardinal;
begin
sConfig := nil;
schm := OpenSCManager(nil, nil, SC_MANAGER_CONNECT);
        if (schm > 0) then
        begin
        schs := OpenService(schm, PChar(Service), SERVICE_QUERY_CONFIG);
                if (schs > 0) then
                begin
                //Call the QueryServiceConfig function to get the required buffer size
                        if QueryServiceConfig(schs,sConfig,0,sNeeded) <> TRUE then
                        begin
                                if GetLastError = ERROR_INSUFFICIENT_BUFFER then
                                begin
                                //Get the memory required by using the Bytes needed var
                                GetMem(sConfig,sNeeded);
                                        if QueryServiceConfig(schs,sConfig,sNeeded,sNeeded) <> TRUE then
                                        begin
                                        MessageDlg(SysErrorMessage(GetLastError),mtError,[MBOK],0);
                                        end
                                        else
                                        begin
                                        //Play with Config Info here
                                        pConfig := PQueryServiceConfigA(sConfig);
                                        ShowMessage(pConfig.lpDisplayName);
                                        end;
                                end;
                        end;
                CloseServiceHandle(schs);
                end;
        CloseServiceHandle(schm);
        end;
end;
0
Become a CompTIA Certified Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

mantra246Author Commented:
Still the same error messages trying the new code.  I'm not sure about 'declaring sConfig as lpServiceConfig rather than pointer ' as it causes an "undeclared identifier" error when i change sConfig: Pointer; to sConfig: lpServiceConfig ;
0
mantra246Author Commented:
In your first code you posted, if i change sConfig: PQueryServiceConfigA; to sConfig: TQueryServiceConfig; the error "Type of actual and formal var parameters must be identical" messages stop - but it gives the error "incompatible types" at the GetMem(sConfig,sNeeded); line.
0
BedouinDNCommented:
How is the QueryServiceConfig function declared for you?
I.E. What exactly is the function asking for?

The original error ("Type of actual and formal var parameters must be identical") means that the code is passing an incorrect variable type to the function.

Bedouin..
0
mantra246Author Commented:
This is from the winsvc.pas file:

{$EXTERNALSYM QueryServiceConfigA}
function QueryServiceConfigA(hService: SC_HANDLE;
  var lpServiceConfig: TQueryServiceConfigA; cbBufSize: DWORD;
  var pcbBytesNeeded: DWORD): BOOL; stdcall;
{$EXTERNALSYM QueryServiceConfigW}
function QueryServiceConfigW(hService: SC_HANDLE;
  var lpServiceConfig: TQueryServiceConfigW; cbBufSize: DWORD;
  var pcbBytesNeeded: DWORD): BOOL; stdcall;
{$EXTERNALSYM QueryServiceConfig}
function QueryServiceConfig(hService: SC_HANDLE;
  var lpServiceConfig: TQueryServiceConfig; cbBufSize: DWORD;
  var pcbBytesNeeded: DWORD): BOOL; stdcall;
0
mantra246Author Commented:
also

//
// Query Service Configuration Structure
//
  PQueryServiceConfigA = ^TQueryServiceConfigA;
  PQueryServiceConfigW = ^TQueryServiceConfigW;
  PQueryServiceConfig = PQueryServiceConfigA;
  {$EXTERNALSYM _QUERY_SERVICE_CONFIGA}
   _QUERY_SERVICE_CONFIGA = record
    dwServiceType: DWORD;
    dwStartType: DWORD;
    dwErrorControl: DWORD;
    lpBinaryPathName: PAnsiChar;
    lpLoadOrderGroup: PAnsiChar;
    dwTagId: DWORD;
    lpDependencies: PAnsiChar;
    lpServiceStartName: PAnsiChar;
    lpDisplayName: PAnsiChar;
  end;
  {$EXTERNALSYM _QUERY_SERVICE_CONFIGW}
   _QUERY_SERVICE_CONFIGW = record
    dwServiceType: DWORD;
    dwStartType: DWORD;
    dwErrorControl: DWORD;
    lpBinaryPathName: PWideChar;
    lpLoadOrderGroup: PWideChar;
    dwTagId: DWORD;
    lpDependencies: PWideChar;
    lpServiceStartName: PWideChar;
    lpDisplayName: PWideChar;
  end;
  {$EXTERNALSYM _QUERY_SERVICE_CONFIG}
  _QUERY_SERVICE_CONFIG = _QUERY_SERVICE_CONFIGA;
  {$EXTERNALSYM QUERY_SERVICE_CONFIGA}
  QUERY_SERVICE_CONFIGA = _QUERY_SERVICE_CONFIGA;
  {$EXTERNALSYM QUERY_SERVICE_CONFIGW}
  QUERY_SERVICE_CONFIGW = _QUERY_SERVICE_CONFIGW;
  {$EXTERNALSYM QUERY_SERVICE_CONFIG}
  QUERY_SERVICE_CONFIG = QUERY_SERVICE_CONFIGA;
  TQueryServiceConfigA = _QUERY_SERVICE_CONFIGA;
  TQueryServiceConfigW = _QUERY_SERVICE_CONFIGW;
  TQueryServiceConfig = TQueryServiceConfigA;
0
BedouinDNCommented:
Unfortunately I have a different declaration of the function.
From WinSvc:
function QueryServiceConfig(hService: SC_HANDLE;
  lpServiceConfig: PQueryServiceConfig; cbBufSize: DWORD;
  var pcbBytesNeeded: DWORD): BOOL; stdcall;

I would advise downloading the latest Win32 API conversion from Marcel van Brakel's site or the Project Jedi website.
This has a translation of the WinSvc.pas file that compiles without error for me and has the same declaration as my WinSvc.pas.

Marcel's site: http://members.chello.nl/m.vanbrakel2

If you unzip the zip file and add the folder to your Library path in Tools->Environment Options->Library, then add JwaWinSvc to your uses clause instead of WinSvc the original code should work OK. (hopefully) :-)



0
mantra246Author Commented:
It's ok - i used your code and played with it a while and it now seems to work fine - although i will have to test it out more and insert some error checking.  It was missing the ^ from sConfig with sConfig set up as a type and a pointer to it.

I shall give you the points though since you were very kind in trying to help and did provide code that i will use.  So i shall be adding some more points for the extra help you gave and making it a grade A.

Thanks for all the help.
0
BedouinDNCommented:
Well thankyou for that, but please do not feel obliged to add points or anything like that. You should really only give what you believe the help is worth.

At any rate, I hope this all works out OK for you

Cheers.
Bedouin..
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mantra246Author Commented:
I am adding extra points to say thank you for going the extra mile on this one with me - it is the only way i can show that i appreciate the work you did on my behalf.   It may only be points but the principle is that what you did was appreciated and should be recognized as such.

Again, thank you for all your help on this one.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.