⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ntservice.c

📁 video linux conference
💻 C
字号:
/***************************************************************************** * ntservice.c: Windows NT/2K/XP service interface ***************************************************************************** * Copyright (C) 2004 VideoLAN * $Id: ntservice.c 10112 2005-03-03 06:58:04Z zorglub $ * * Authors: Gildas Bazin <gbazin@videolan.org> * * 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 of the License, 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 program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h>#include <vlc/vlc.h>#include <vlc/intf.h>#define VLCSERVICENAME "VLC media player"/***************************************************************************** * Module descriptor *****************************************************************************/static int  Activate( vlc_object_t * );static void Close   ( vlc_object_t * );#define INSTALL_TEXT N_( "Install Windows Service" )#define INSTALL_LONGTEXT N_( \    "If enabled the interface will install the Service and exit." )#define UNINSTALL_TEXT N_( "Uninstall Windows Service" )#define UNINSTALL_LONGTEXT N_( \    "If enabled the interface will uninstall the Service and exit." )#define NAME_TEXT N_( "Display name of the Service" )#define NAME_LONGTEXT N_( \    "This allows you to change the display name of the Service." )#define OPTIONS_TEXT N_("Configuration options")#define OPTIONS_LONGTEXT N_( \    "This option allows you to specify configuration options that will be " \    "used by the Service (eg. --foo=bar --no-foobar). It should be specified "\    "at install time so the Service is properly configured.")#define EXTRAINTF_TEXT N_("Extra interface modules")#define EXTRAINTF_LONGTEXT N_( \    "This option allows you to select additional interfaces spawned by the " \    "Service. It should be specified at install time so the Service is " \    "properly configured. Use a comma separated list of interface modules. " \    "(common values are: logger, sap, rc, http)")vlc_module_begin();    set_shortname( _("NT Service"));    set_description( _("Windows Service interface") );    set_category( CAT_INTERFACE );    set_subcategory( SUBCAT_INTERFACE_CONTROL );    add_bool( "ntservice-install", 0, NULL,              INSTALL_TEXT, INSTALL_LONGTEXT, VLC_TRUE );    add_bool( "ntservice-uninstall", 0, NULL,              UNINSTALL_TEXT, UNINSTALL_LONGTEXT, VLC_TRUE );    add_string ( "ntservice-name", VLCSERVICENAME, NULL,                 NAME_TEXT, NAME_LONGTEXT, VLC_TRUE );    add_string ( "ntservice-options", NULL, NULL,                 OPTIONS_TEXT, OPTIONS_LONGTEXT, VLC_TRUE );    add_string ( "ntservice-extraintf", NULL, NULL,                 EXTRAINTF_TEXT, EXTRAINTF_LONGTEXT, VLC_TRUE );    set_capability( "interface", 0 );    set_callbacks( Activate, Close );vlc_module_end();struct intf_sys_t{    SERVICE_STATUS_HANDLE hStatus;    SERVICE_STATUS status;    char *psz_service;};/***************************************************************************** * Local prototypes *****************************************************************************/static void Run( intf_thread_t *p_intf );static int NTServiceInstall( intf_thread_t *p_intf );static int NTServiceUninstall( intf_thread_t *p_intf );static void WINAPI ServiceDispatch( DWORD numArgs, char **args );static void WINAPI ServiceCtrlHandler( DWORD control );/* We need this global */static intf_thread_t *p_global_intf;/***************************************************************************** * Activate: initialize and create stuff *****************************************************************************/static int Activate( vlc_object_t *p_this ){    intf_thread_t *p_intf = (intf_thread_t*)p_this;    /* Only works on NT/2K/XP */    if( !IS_WINNT ) return VLC_EGENERIC;    p_intf->pf_run = Run;    return VLC_SUCCESS;}/***************************************************************************** * Close: destroy interface *****************************************************************************/void Close( vlc_object_t *p_this ){}/***************************************************************************** * Run: interface thread *****************************************************************************/static void Run( intf_thread_t *p_intf ){    intf_thread_t *p_extraintf;    SERVICE_TABLE_ENTRY dispatchTable[] =    {        { VLCSERVICENAME, &ServiceDispatch },        { NULL, NULL }    };    p_global_intf = p_intf;    p_intf->p_sys = alloca( sizeof( intf_sys_t ) );    p_intf->p_sys->psz_service = config_GetPsz( p_intf, "ntservice-name" );    p_intf->p_sys->psz_service = p_intf->p_sys->psz_service ?        p_intf->p_sys->psz_service : strdup(VLCSERVICENAME);    if( config_GetInt( p_intf, "ntservice-install" ) )    {        NTServiceInstall( p_intf );        return;    }    if( config_GetInt( p_intf, "ntservice-uninstall" ) )    {        NTServiceUninstall( p_intf );        return;    }    if( StartServiceCtrlDispatcher( dispatchTable ) == 0 )    {        msg_Err( p_intf, "StartServiceCtrlDispatcher failed" );    }    free( p_intf->p_sys->psz_service );    /* Stop and destroy the interfaces we spawned */    while( (p_extraintf = vlc_object_find(p_intf, VLC_OBJECT_INTF, FIND_CHILD)))    {        intf_StopThread( p_extraintf );        vlc_object_detach( p_extraintf );        vlc_object_release( p_extraintf );        intf_Destroy( p_extraintf );    }    /* Make sure we exit (In case other interfaces have been spawned) */    p_intf->p_vlc->b_die = VLC_TRUE;}/***************************************************************************** * NT Service utility functions *****************************************************************************/static int NTServiceInstall( intf_thread_t *p_intf ){    intf_sys_t *p_sys  = p_intf->p_sys;    char psz_path[10*MAX_PATH], psz_pathtmp[MAX_PATH], *psz_extra;    SC_HANDLE handle = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );    if( handle == NULL )    {        msg_Err( p_intf, "could not connect to SCM database" );        return VLC_EGENERIC;    }    /* Find out the filename of ourselves so we can install it to the     * service control manager */    GetModuleFileName( NULL, psz_pathtmp, MAX_PATH );    sprintf( psz_path, "\"%s\" -I "MODULE_STRING, psz_pathtmp );    psz_extra = config_GetPsz( p_intf, "ntservice-extraintf" );    if( psz_extra && *psz_extra )    {        strcat( psz_path, " --ntservice-extraintf " );        strcat( psz_path, psz_extra );    }    if( psz_extra ) free( psz_extra );    psz_extra = config_GetPsz( p_intf, "ntservice-options" );    if( psz_extra && *psz_extra )    {        strcat( psz_path, " " );        strcat( psz_path, psz_extra );    }    if( psz_extra ) free( psz_extra );    SC_HANDLE service =        CreateService( handle, p_sys->psz_service, p_sys->psz_service,                       GENERIC_READ | GENERIC_EXECUTE,                       SERVICE_WIN32_OWN_PROCESS,                       SERVICE_AUTO_START, SERVICE_ERROR_IGNORE,                       psz_path, NULL, NULL, NULL, NULL, NULL );    if( service == NULL )    {        if( GetLastError() != ERROR_SERVICE_EXISTS )        {            msg_Err( p_intf, "could not create new service: \"%s\" (%s)",                     p_sys->psz_service ,psz_path );            CloseServiceHandle( handle );            return VLC_EGENERIC;        }        else        {            msg_Warn( p_intf, "service \"%s\" already exists",                      p_sys->psz_service );        }    }    else    {        msg_Warn( p_intf, "service successfuly created" );    }    if( service ) CloseServiceHandle( service );    CloseServiceHandle( handle );    return VLC_SUCCESS;}static int NTServiceUninstall( intf_thread_t *p_intf ){    intf_sys_t *p_sys  = p_intf->p_sys;    SC_HANDLE handle = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );    if( handle == NULL )    {        msg_Err( p_intf, "could not connect to SCM database" );        return VLC_EGENERIC;    }    /* First, open a handle to the service */    SC_HANDLE service = OpenService( handle, p_sys->psz_service, DELETE );    if( service == NULL )    {        msg_Err( p_intf, "could not open service" );        CloseServiceHandle( handle );        return VLC_EGENERIC;    }    /* Remove the service */    if( !DeleteService( service ) )    {        msg_Err( p_intf, "could not delete service \"%s\"",                 p_sys->psz_service );    }    else    {        msg_Dbg( p_intf, "service deleted successfuly" );    }    CloseServiceHandle( service );    CloseServiceHandle( handle );    return VLC_SUCCESS;}static void WINAPI ServiceDispatch( DWORD numArgs, char **args ){    intf_thread_t *p_intf = (intf_thread_t *)p_global_intf;    intf_sys_t    *p_sys  = p_intf->p_sys;    char *psz_modules, *psz_parser;    /* We have to initialize the service-specific stuff */    memset( &p_sys->status, 0, sizeof(SERVICE_STATUS) );    p_sys->status.dwServiceType = SERVICE_WIN32;    p_sys->status.dwCurrentState = SERVICE_START_PENDING;    p_sys->status.dwControlsAccepted = SERVICE_ACCEPT_STOP;    p_sys->hStatus =        RegisterServiceCtrlHandler( p_sys->psz_service, &ServiceCtrlHandler );    if( p_sys->hStatus == (SERVICE_STATUS_HANDLE)0 )    {        msg_Err( p_intf, "failed to register service control handler" );        return;    }    /*     * Load background interfaces     */    psz_modules = config_GetPsz( p_intf, "ntservice-extraintf" );    psz_parser = psz_modules;    while( psz_parser && *psz_parser )    {        char *psz_module, *psz_temp;        psz_module = psz_parser;        psz_parser = strchr( psz_module, ',' );        if( psz_parser )        {            *psz_parser = '\0';            psz_parser++;        }        psz_temp = (char *)malloc( strlen(psz_module) + sizeof(",none") );        if( psz_temp )        {            intf_thread_t *p_new_intf;            sprintf( psz_temp, "%s,none", psz_module );            /* Try to create the interface */            p_new_intf = intf_Create( p_intf, psz_temp );            if( p_new_intf == NULL )            {                msg_Err( p_intf, "interface \"%s\" initialization failed",                         psz_temp );                free( psz_temp );                continue;            }            /* Try to run the interface */            p_new_intf->b_block = VLC_FALSE;            if( intf_RunThread( p_new_intf ) )            {                vlc_object_detach( p_new_intf );                intf_Destroy( p_new_intf );                msg_Err( p_intf, "interface \"%s\" cannot run", psz_temp );            }            free( psz_temp );        }    }    if( psz_modules )    {        free( psz_modules );    }    /* Initialization complete - report running status */    p_sys->status.dwCurrentState = SERVICE_RUNNING;    p_sys->status.dwCheckPoint   = 0;    p_sys->status.dwWaitHint     = 0;    SetServiceStatus( p_sys->hStatus, &p_sys->status );}static void WINAPI ServiceCtrlHandler( DWORD control ){    intf_thread_t *p_intf = (intf_thread_t *)p_global_intf;    intf_sys_t    *p_sys  = p_intf->p_sys;    switch( control )    {    case SERVICE_CONTROL_SHUTDOWN:    case SERVICE_CONTROL_STOP:        p_sys->status.dwCurrentState = SERVICE_STOPPED;        p_sys->status.dwWin32ExitCode = 0;        p_sys->status.dwCheckPoint = 0;        p_sys->status.dwWaitHint = 0;        break;    case SERVICE_CONTROL_INTERROGATE:        /* just set the current state to whatever it is... */        break;    }    SetServiceStatus( p_sys->hStatus, &p_sys->status );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -