From d8c6c562f3e5815217abeec5e145432bcff3e6df Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Mon, 5 Sep 2016 17:07:11 +0200 Subject: [PATCH] =?UTF-8?q?2016-09-05=2017:04=20UTC+0200=20Viktor=20Szakat?= =?UTF-8?q?s=20(vszakats=20users.noreply.github.com)=20=20=20*=20contrib/h?= =?UTF-8?q?bwin/hbwin.ch=20=20=20*=20contrib/hbwin/hbwin.hbp=20=20=20*=20c?= =?UTF-8?q?ontrib/hbwin/hbwin.hbx=20=20=20+=20contrib/hbwin/win=5Fsvc=5F2.?= =?UTF-8?q?c=20=20=20*=20contrib/hbwin/win=5Fsvc.c=20->=20contrib/hbwin/wi?= =?UTF-8?q?n=5Fsvc=5F1.c=20=20=20=20=20+=20add=20function=20win=5FServiceR?= =?UTF-8?q?un(=20,=20[...]=20)=20->=20=20=20=20=20=20=20?= =?UTF-8?q?=20to=20start=20a=20service=20by=20name=20=20=20=20=20+=20add?= =?UTF-8?q?=20WIN=5FSERVICE=5FCONTROL=5F*=20constants=20=20=20=20=20+=20ad?= =?UTF-8?q?d=20function=20win=5FServiceControl(=20,=20=20)=20->=20=20=20=20=20=20+=20add=202nd=20parameter?= =?UTF-8?q?=20to=20win=5FServiceDelete(=20,=20=20)=20->=20=20=20=20=20=20=20=20=20will=20attempt=20to=20?= =?UTF-8?q?stop=20the=20service=20before=20deleting=20it.=20=20=20=20=20%?= =?UTF-8?q?=20separate=20service=20management=20functions=20and=20Harbour?= =?UTF-8?q?=20app-as-service=20=20=20=20=20=20=20support=20functions=20int?= =?UTF-8?q?o=20separate=20sources=20=20=20=20=20;=20build-tested=20only,?= =?UTF-8?q?=20function=20names=20not=20finalized.=20=20=20=20=20*=20set=20?= =?UTF-8?q?wapi=5FGetLastError()=20more=20consistently=20=20=20=20=20+=20w?= =?UTF-8?q?in=5FServiceInstall()=20add=20two=20new=20optional=20parameters?= =?UTF-8?q?:=20=20=20=20=20=20=20=20(5th)=20and=20?= =?UTF-8?q?=20(6th)=20=20=20=20=20!=20win=5FServiceInstall()=20do=20not=20?= =?UTF-8?q?convert=20an=20omitted=20=20=20=20=20=20=20=20(2n?= =?UTF-8?q?d)=20parameter=20to=20empty=20string,=20pass=20it=20=20=20=20?= =?UTF-8?q?=20=20=20to=20Windows=20as=20NULL=20instead=20=20=20=20=20%=20u?= =?UTF-8?q?se=20HB=5FIT=5FEVALITEM=20instead=20of=20(=20HB=5FIT=5FBLOCK=20?= =?UTF-8?q?|=20HB=5FIT=5FSYMBOL=20)=20=20=20=20=20;=20Above=20patches=20co?= =?UTF-8?q?me=20from=203.4=20fork=20commits=20below:=20=20=20=20=20=20=202?= =?UTF-8?q?015-09-03=2018:52=20UTC+0200=20Viktor=20Szakats=20(vszakats=20u?= =?UTF-8?q?sers.noreply.github.com)=20=20=20=20=20=20=202015-09-02=2019:54?= =?UTF-8?q?=20UTC+0200=20Viktor=20Szakats=20(vszakats=20users.noreply.gith?= =?UTF-8?q?ub.com)=20=20=20=20=20=20=202015-09-02=2018:43=20UTC+0200=20Vik?= =?UTF-8?q?tor=20Szakats=20(vszakats=20users.noreply.github.com)=20=20=20?= =?UTF-8?q?=20=20=20=202015-04-03=2011:43=20UTC+0200=20Viktor=20Szakats=20?= =?UTF-8?q?(vszakats=20users.noreply.github.com)=20=20=20=20=20=20=202014-?= =?UTF-8?q?01-29=2002:15=20UTC+0100=20Viktor=20Szak=C3=A1ts=20(vszakats=20?= =?UTF-8?q?users.noreply.github.com)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChangeLog.txt | 29 +++ contrib/hbwin/hbwin.ch | 11 + contrib/hbwin/hbwin.hbp | 3 +- contrib/hbwin/hbwin.hbx | 2 + contrib/hbwin/{win_svc.c => win_svc_1.c} | 150 +++--------- contrib/hbwin/win_svc_2.c | 280 +++++++++++++++++++++++ 6 files changed, 352 insertions(+), 123 deletions(-) rename contrib/hbwin/{win_svc.c => win_svc_1.c} (60%) create mode 100644 contrib/hbwin/win_svc_2.c diff --git a/ChangeLog.txt b/ChangeLog.txt index 55e06972ef..e02eb87758 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,35 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2016-09-05 17:04 UTC+0200 Viktor Szakats (vszakats users.noreply.github.com) + * contrib/hbwin/hbwin.ch + * contrib/hbwin/hbwin.hbp + * contrib/hbwin/hbwin.hbx + + contrib/hbwin/win_svc_2.c + * contrib/hbwin/win_svc.c -> contrib/hbwin/win_svc_1.c + + add function win_ServiceRun( , [...] ) -> + to start a service by name + + add WIN_SERVICE_CONTROL_* constants + + add function win_ServiceControl( , ) -> + + add 2nd parameter to win_ServiceDelete( , ) -> + will attempt to stop the service before deleting it. + % separate service management functions and Harbour app-as-service + support functions into separate sources + ; build-tested only, function names not finalized. + * set wapi_GetLastError() more consistently + + win_ServiceInstall() add two new optional parameters: + (5th) and (6th) + ! win_ServiceInstall() do not convert an omitted + (2nd) parameter to empty string, pass it + to Windows as NULL instead + % use HB_IT_EVALITEM instead of ( HB_IT_BLOCK | HB_IT_SYMBOL ) + ; Above patches come from 3.4 fork commits below: + 2015-09-03 18:52 UTC+0200 Viktor Szakats (vszakats users.noreply.github.com) + 2015-09-02 19:54 UTC+0200 Viktor Szakats (vszakats users.noreply.github.com) + 2015-09-02 18:43 UTC+0200 Viktor Szakats (vszakats users.noreply.github.com) + 2015-04-03 11:43 UTC+0200 Viktor Szakats (vszakats users.noreply.github.com) + 2014-01-29 02:15 UTC+0100 Viktor Szakáts (vszakats users.noreply.github.com) + 2016-08-10 20:12 UTC+0300 Mindaugas Kavaliauskas (dbtopas/at/dbtopas.lt) * contrib/rddads/ads.ch + 64bit server type constants included diff --git a/contrib/hbwin/hbwin.ch b/contrib/hbwin/hbwin.ch index 80f905eda9..185915bb2b 100644 --- a/contrib/hbwin/hbwin.ch +++ b/contrib/hbwin/hbwin.ch @@ -672,6 +672,17 @@ #define WIN_SERVICE_DISABLED 0x00000004 #define WIN_SERVICE_SYSTEM_START 0x00000001 +/* win_serviceControl() control codes */ +#define WIN_SERVICE_CONTROL_STOP 0x00000001 +#define WIN_SERVICE_CONTROL_PAUSE 0x00000002 +#define WIN_SERVICE_CONTROL_CONTINUE 0x00000003 +#define WIN_SERVICE_CONTROL_INTERROGATE 0x00000004 +#define WIN_SERVICE_CONTROL_PARAMCHANGE 0x00000006 +#define WIN_SERVICE_CONTROL_NETBINDADD 0x00000007 +#define WIN_SERVICE_CONTROL_NETBINDREMOVE 0x00000008 +#define WIN_SERVICE_CONTROL_NETBINDENABLE 0x00000009 +#define WIN_SERVICE_CONTROL_NETBINDDISABLE 0x0000000A + /* wapi_MessageBox()/wapi_MessageBeep() flags */ #define WIN_MB_OK 0x00000000 #define WIN_MB_OKCANCEL 0x00000001 diff --git a/contrib/hbwin/hbwin.hbp b/contrib/hbwin/hbwin.hbp index 652103719e..9d26d378b5 100644 --- a/contrib/hbwin/hbwin.hbp +++ b/contrib/hbwin/hbwin.hbp @@ -59,7 +59,8 @@ win_prn3.c win_regc.c win_rpc.c win_shell.c -win_svc.c +win_svc_1.c +win_svc_2.c oleauto.prg axfunc.prg diff --git a/contrib/hbwin/hbwin.hbx b/contrib/hbwin/hbwin.hbx index b2baf4bcaf..18b541cc2e 100644 --- a/contrib/hbwin/hbwin.hbx +++ b/contrib/hbwin/hbwin.hbx @@ -394,9 +394,11 @@ DYNAMIC win_regSetValueEx DYNAMIC win_regWrite DYNAMIC win_ReportEvent DYNAMIC win_RunDetached +DYNAMIC win_serviceControl DYNAMIC win_serviceDelete DYNAMIC win_serviceGetStatus DYNAMIC win_serviceInstall +DYNAMIC win_serviceRun DYNAMIC win_serviceSetExitCode DYNAMIC win_serviceSetStatus DYNAMIC win_serviceStart diff --git a/contrib/hbwin/win_svc.c b/contrib/hbwin/win_svc_1.c similarity index 60% rename from contrib/hbwin/win_svc.c rename to contrib/hbwin/win_svc_1.c index 6d700b9e4a..00d3d42a01 100644 --- a/contrib/hbwin/win_svc.c +++ b/contrib/hbwin/win_svc_1.c @@ -1,7 +1,7 @@ /* * Windows Service API * - * Copyright 2010 Jose Luis Capel - + * Copyright 2010 Jose Luis Capel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -52,7 +52,7 @@ #if ! defined( HB_OS_WIN_CE ) #if defined( __POCC__ ) || defined( __XCC__ ) -# include /* it's disabled by WIN32_LEAN_AND_MEAN */ + #include /* it's disabled by WIN32_LEAN_AND_MEAN */ #endif static SERVICE_STATUS s_ServiceStatus; @@ -76,7 +76,7 @@ static VOID WINAPI hbwin_SvcControlHandler( DWORD fdwControl ) return; } - SetServiceStatus( s_hStatus, &s_ServiceStatus ); /* Report current status */ + SetServiceStatus( s_hStatus, &s_ServiceStatus ); /* Report current status */ } static VOID WINAPI hbwin_SvcMainFunction( DWORD dwArgc, LPTSTR * lpszArgv ) @@ -137,18 +137,22 @@ static VOID WINAPI hbwin_SvcMainFunction( DWORD dwArgc, LPTSTR * lpszArgv ) HB_FUNC( WIN_SERVICEGETSTATUS ) { #if ! defined( HB_OS_WIN_CE ) - hb_retnl( s_ServiceStatus.dwCurrentState ); + hb_retnint( s_ServiceStatus.dwCurrentState ); #else - hb_retnl( 0 ); + hb_retnint( 0 ); #endif } HB_FUNC( WIN_SERVICESETSTATUS ) { #if ! defined( HB_OS_WIN_CE ) + HB_BOOL bRetVal; s_ServiceStatus.dwCurrentState = ( DWORD ) hb_parnl( 1 ); - hb_retl( SetServiceStatus( s_hStatus, &s_ServiceStatus ) ); + bRetVal = ( HB_BOOL ) SetServiceStatus( s_hStatus, &s_ServiceStatus ); + hbwapi_SetLastError( GetLastError() ); + hb_retl( bRetVal ); #else + hbwapi_SetLastError( ERROR_NOT_SUPPORTED ); hb_retl( HB_FALSE ); #endif } @@ -156,9 +160,13 @@ HB_FUNC( WIN_SERVICESETSTATUS ) HB_FUNC( WIN_SERVICESETEXITCODE ) { #if ! defined( HB_OS_WIN_CE ) + HB_BOOL bRetVal; s_ServiceStatus.dwWin32ExitCode = ( DWORD ) hb_parnl( 1 ); - hb_retl( SetServiceStatus( s_hStatus, &s_ServiceStatus ) ); + bRetVal = ( HB_BOOL ) SetServiceStatus( s_hStatus, &s_ServiceStatus ); + hbwapi_SetLastError( GetLastError() ); + hb_retl( bRetVal ); #else + hbwapi_SetLastError( ERROR_NOT_SUPPORTED ); hb_retl( HB_FALSE ); #endif } @@ -166,122 +174,20 @@ HB_FUNC( WIN_SERVICESETEXITCODE ) HB_FUNC( WIN_SERVICESTOP ) { #if ! defined( HB_OS_WIN_CE ) + HB_BOOL bRetVal; s_ServiceStatus.dwCurrentState = SERVICE_STOPPED; - SetServiceStatus( s_hStatus, &s_ServiceStatus ); -#endif -} - -HB_FUNC( WIN_SERVICEINSTALL ) -{ - HB_BOOL bRetVal = HB_FALSE; - -#if ! defined( HB_OS_WIN_CE ) - - void * hPath; - LPCTSTR lpPath = HB_PARSTR( 3, &hPath, NULL ); - - TCHAR lpPathBuffer[ MAX_PATH ]; - - if( lpPath == NULL ) - { - if( GetModuleFileName( NULL, lpPathBuffer, HB_SIZEOFARRAY( lpPathBuffer ) ) ) - lpPath = lpPathBuffer; - else - hbwapi_SetLastError( GetLastError() ); - } - - if( lpPath ) - { - SC_HANDLE schSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); - - if( schSCM ) - { - SC_HANDLE schSrv; - - void * hServiceName; - void * hDisplayName; - - LPCTSTR lpServiceName = HB_PARSTRDEF( 1, &hServiceName, NULL ); - LPCTSTR lpDisplayName = HB_PARSTRDEF( 2, &hDisplayName, NULL ); - - schSrv = CreateService( schSCM, /* SCM database */ - lpServiceName, /* name of service */ - lpDisplayName, /* service name to display */ - SERVICE_ALL_ACCESS, /* desired access */ - SERVICE_WIN32_OWN_PROCESS, /* service type */ - HB_ISNUM( 4 ) ? ( DWORD ) hb_parnl( 4 ) : SERVICE_DEMAND_START, - /* start type */ - SERVICE_ERROR_NORMAL, /* error control type */ - lpPath, /* path to service's binary */ - NULL, /* no load ordering group */ - NULL, /* no tag identifier */ - NULL, /* no dependencies */ - NULL, /* LocalSystem account */ - NULL ); /* no password */ - - if( schSrv ) - { - bRetVal = HB_TRUE; - - CloseServiceHandle( schSrv ); - } - else - hbwapi_SetLastError( GetLastError() ); - - hb_strfree( hServiceName ); - hb_strfree( hDisplayName ); - - CloseServiceHandle( schSCM ); - } - else - hbwapi_SetLastError( GetLastError() ); - } - - hb_strfree( hPath ); - -#endif + bRetVal = ( HB_BOOL ) SetServiceStatus( s_hStatus, &s_ServiceStatus ); + hbwapi_SetLastError( GetLastError() ); hb_retl( bRetVal ); -} - -HB_FUNC( WIN_SERVICEDELETE ) -{ - HB_BOOL bRetVal = HB_FALSE; - -#if ! defined( HB_OS_WIN_CE ) - SC_HANDLE schSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); - - if( schSCM ) - { - void * hServiceName; - - SC_HANDLE schSrv = OpenService( schSCM, - HB_PARSTRDEF( 1, &hServiceName, NULL ), - SERVICE_ALL_ACCESS ); - - if( schSrv ) - { - /* TODO: check if service is up and then stop it */ - - bRetVal = ( HB_BOOL ) DeleteService( schSrv ); - - CloseServiceHandle( schSrv ); - } - else - hbwapi_SetLastError( GetLastError() ); - - hb_strfree( hServiceName ); - - CloseServiceHandle( schSCM ); - } - else - hbwapi_SetLastError( GetLastError() ); +#else + hbwapi_SetLastError( ERROR_NOT_SUPPORTED ); + hb_retl( HB_FALSE ); #endif - hb_retl( bRetVal ); } HB_FUNC( WIN_SERVICESTART ) { - HB_BOOL bRetVal = HB_FALSE; + HB_BOOL bRetVal; #if ! defined( HB_OS_WIN_CE ) PHB_ITEM pEntryFunc; @@ -296,7 +202,7 @@ HB_FUNC( WIN_SERVICESTART ) s_pHarbourEntryFunc = NULL; } - pEntryFunc = hb_param( 2, HB_IT_BLOCK | HB_IT_SYMBOL ); + pEntryFunc = hb_param( 2, HB_IT_EVALITEM ); if( pEntryFunc ) s_pHarbourEntryFunc = hb_itemNew( pEntryFunc ); @@ -307,11 +213,11 @@ HB_FUNC( WIN_SERVICESTART ) lpServiceTable[ 1 ].lpServiceName = NULL; lpServiceTable[ 1 ].lpServiceProc = NULL; - if( StartServiceCtrlDispatcher( lpServiceTable ) ) - bRetVal = HB_TRUE; - else - hbwapi_SetLastError( GetLastError() ); - + bRetVal = ( HB_BOOL ) StartServiceCtrlDispatcher( lpServiceTable ); + hbwapi_SetLastError( GetLastError() ); +#else + bRetVal = HB_FALSE; + hbwapi_SetLastError( ERROR_NOT_SUPPORTED ); #endif hb_retl( bRetVal ); } diff --git a/contrib/hbwin/win_svc_2.c b/contrib/hbwin/win_svc_2.c new file mode 100644 index 0000000000..d4f2f3652b --- /dev/null +++ b/contrib/hbwin/win_svc_2.c @@ -0,0 +1,280 @@ +/* + * Windows Service Management API + * + * Copyright 2010 Jose Luis Capel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.txt. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site https://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +#include "hbwapi.h" + +HB_FUNC( WIN_SERVICEINSTALL ) +{ + HB_BOOL bRetVal = HB_FALSE; + +#if ! defined( HB_OS_WIN_CE ) + + void * hPath; + LPCTSTR lpPath = HB_PARSTR( 3, &hPath, NULL ); + + TCHAR lpPathBuffer[ MAX_PATH ]; + + if( lpPath == NULL ) + { + if( GetModuleFileName( NULL, lpPathBuffer, HB_SIZEOFARRAY( lpPathBuffer ) ) ) + lpPath = lpPathBuffer; + else + hbwapi_SetLastError( GetLastError() ); + } + + if( lpPath ) + { + SC_HANDLE schSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); + + if( schSCM ) + { + SC_HANDLE schSrv; + + void * hServiceName; + void * hDisplayName; + void * hAccountName; + void * hPassword; + + LPCTSTR lpServiceName = HB_PARSTRDEF( 1, &hServiceName, NULL ); + LPCTSTR lpDisplayName = HB_PARSTR( 2, &hDisplayName, NULL ); + LPCTSTR lpAccountName = HB_PARSTR( 5, &hAccountName, NULL ); + LPCTSTR lpPassword = HB_PARSTR( 6, &hPassword, NULL ); + + schSrv = CreateService( schSCM, /* SCM database */ + lpServiceName, /* name of service */ + lpDisplayName, /* service name to display */ + SERVICE_ALL_ACCESS, /* desired access */ + SERVICE_WIN32_OWN_PROCESS, /* service type */ + ( DWORD ) hb_parnldef( 4, SERVICE_DEMAND_START ), /* start type */ + SERVICE_ERROR_NORMAL, /* error control type */ + lpPath, /* path to service's binary */ + NULL, /* no load ordering group */ + NULL, /* no tag identifier */ + NULL, /* no dependencies */ + lpAccountName, /* default: LocalSystem account */ + lpPassword ); /* default: no password */ + + hbwapi_SetLastError( GetLastError() ); + + if( schSrv ) + { + bRetVal = HB_TRUE; + + CloseServiceHandle( schSrv ); + } + + hb_strfree( hServiceName ); + hb_strfree( hDisplayName ); + hb_strfree( hAccountName ); + hb_strfree( hPassword ); + + CloseServiceHandle( schSCM ); + } + else + hbwapi_SetLastError( GetLastError() ); + } + + hb_strfree( hPath ); +#else + hbwapi_SetLastError( ERROR_NOT_SUPPORTED ); +#endif + + hb_retl( bRetVal ); +} + +HB_FUNC( WIN_SERVICEDELETE ) +{ + HB_BOOL bRetVal = HB_FALSE; + +#if ! defined( HB_OS_WIN_CE ) + SC_HANDLE schSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); + + if( schSCM ) + { + void * hServiceName; + + SC_HANDLE schSrv = OpenService( schSCM, + HB_PARSTRDEF( 1, &hServiceName, NULL ), + SERVICE_ALL_ACCESS ); + + if( schSrv ) + { + if( hb_parl( 2 ) ) /* Check if service is up and stop it */ + { + SERVICE_STATUS ssStatus; + + if( ControlService( schSrv, SERVICE_CONTROL_STOP, &ssStatus ) ) + { + while( ssStatus.dwCurrentState != SERVICE_STOPPED && + QueryServiceStatus( schSrv, &ssStatus ) ) + hb_idleSleep( 1.0 ); + } + } + + bRetVal = ( HB_BOOL ) DeleteService( schSrv ); + hbwapi_SetLastError( GetLastError() ); + + CloseServiceHandle( schSrv ); + } + else + hbwapi_SetLastError( GetLastError() ); + + hb_strfree( hServiceName ); + + CloseServiceHandle( schSCM ); + } + else + hbwapi_SetLastError( GetLastError() ); +#else + hbwapi_SetLastError( ERROR_NOT_SUPPORTED ); +#endif + hb_retl( bRetVal ); +} + +HB_FUNC( WIN_SERVICECONTROL ) +{ + HB_BOOL bRetVal = HB_FALSE; + +#if ! defined( HB_OS_WIN_CE ) + SC_HANDLE schSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); + + if( schSCM ) + { + void * hServiceName; + + SC_HANDLE schSrv = OpenService( schSCM, + HB_PARSTRDEF( 1, &hServiceName, NULL ), + SERVICE_ALL_ACCESS ); + + if( schSrv ) + { + SERVICE_STATUS ssStatus; + memset( &ssStatus, 0, sizeof( ssStatus ) ); + bRetVal = ( HB_BOOL ) ControlService( schSrv, ( DWORD ) hb_parnl( 2 ), &ssStatus ); + hbwapi_SetLastError( GetLastError() ); + + CloseServiceHandle( schSrv ); + } + else + hbwapi_SetLastError( GetLastError() ); + + hb_strfree( hServiceName ); + + CloseServiceHandle( schSCM ); + } + else + hbwapi_SetLastError( GetLastError() ); +#else + hbwapi_SetLastError( ERROR_NOT_SUPPORTED ); +#endif + hb_retl( bRetVal ); +} + +HB_FUNC( WIN_SERVICERUN ) +{ + HB_BOOL bRetVal = HB_FALSE; + +#if ! defined( HB_OS_WIN_CE ) + SC_HANDLE schSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); + + if( schSCM ) + { + void * hServiceName; + + SC_HANDLE schSrv = OpenService( schSCM, + HB_PARSTRDEF( 1, &hServiceName, NULL ), + SERVICE_ALL_ACCESS ); + + if( schSrv ) + { + DWORD dwArgs, pos; + void ** hArgs; + LPCTSTR * lpArgs; + + if( hb_pcount() >= 2 ) + { + dwArgs = hb_pcount() - 1; + hArgs = ( void ** ) hb_xgrab( dwArgs * sizeof( void * ) ); + lpArgs = ( LPCTSTR * ) hb_xgrab( dwArgs * sizeof( LPCTSTR ) ); + + for( pos = 0; pos < dwArgs; ++pos ) + lpArgs[ pos ] = HB_PARSTRDEF( pos + 2, &hArgs[ pos ], NULL ); + } + else + { + dwArgs = 0; + hArgs = NULL; + lpArgs = NULL; + } + + bRetVal = ( HB_BOOL ) StartService( schSrv, dwArgs, lpArgs ); + hbwapi_SetLastError( GetLastError() ); + + if( hArgs ) + { + for( pos = 0; pos < dwArgs; ++pos ) + hb_strfree( hArgs[ pos ] ); + + hb_xfree( hArgs ); + hb_xfree( lpArgs ); + } + + CloseServiceHandle( schSrv ); + } + else + hbwapi_SetLastError( GetLastError() ); + + hb_strfree( hServiceName ); + + CloseServiceHandle( schSCM ); + } + else + hbwapi_SetLastError( GetLastError() ); +#else + hbwapi_SetLastError( ERROR_NOT_SUPPORTED ); +#endif + hb_retl( bRetVal ); +}