-/*
- * Copyright 2001-2007 Internet2
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * shar_win32.cpp -- the SHAR "main" code on Win32
- *
- * Created By: Scott Cantor (cantor.2@osu.edu)
- *
- * $Id$
- */
-
-#include "config_win32.h"
-
-#define _CRT_NONSTDC_NO_DEPRECATE 1
-#define _CRT_SECURE_NO_DEPRECATE 1
-
-#include <shib-target/shib-target.h>
-
-extern bool shibd_shutdown; // signals shutdown to Unix side
-extern const char* shar_schemadir;
-extern const char* shar_config;
-extern bool shar_checkonly;
-
-// internal variables
-SERVICE_STATUS ssStatus; // current status of the service
-SERVICE_STATUS_HANDLE sshStatusHandle;
-DWORD dwErr = 0;
-BOOL bConsole = FALSE;
-char szErr[256];
-LPCSTR lpszInstall = NULL;
-LPCSTR lpszRemove = NULL;
-
-// internal function prototypes
-VOID WINAPI service_ctrl(DWORD dwCtrlCode);
-VOID WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv);
-VOID CmdInstallService(LPCSTR);
-VOID CmdRemoveService(LPCSTR);
-LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize );
-
-BOOL LogEvent(
- LPCTSTR lpUNCServerName,
- WORD wType,
- DWORD dwEventID,
- PSID lpUserSid,
- LPCTSTR message);
-
-VOID ServiceStart(DWORD dwArgc, LPSTR *lpszArgv);
-VOID ServiceStop();
-BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
-void AddToMessageLog(LPSTR lpszMsg);
-
-BOOL WINAPI BreakHandler(DWORD dwCtrlType)
-{
- switch(dwCtrlType)
- {
- case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate
- case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in console mode
- ServiceStop();
- return TRUE;
- }
- return FALSE;
-}
-
-
-int real_main(int); // The revised two-phase main() in shar.cpp
-
-int main(int argc, char *argv[])
-{
- int i=1;
- while ((argc > i) && ((*argv[i] == '-') || (*argv[i] == '/')))
- {
- if (_stricmp("install", argv[i]+1) == 0)
- {
- if (argc > ++i)
- lpszInstall = argv[i++];
- }
- else if (_stricmp("remove", argv[i]+1) == 0)
- {
- if (argc > ++i)
- lpszRemove = argv[i++];
- }
- else if (_stricmp( "console", argv[i]+1) == 0)
- {
- i++;
- bConsole = TRUE;
- }
- else if (_stricmp( "check", argv[i]+1) == 0)
- {
- i++;
- bConsole = TRUE;
- shar_checkonly=true;
- }
- else if (_stricmp( "config", argv[i]+1) == 0)
- {
- if (argc > ++i)
- shar_config = argv[i++];
- }
- else if (_stricmp( "schemadir", argv[i]+1) == 0)
- {
- if (argc > ++i)
- shar_schemadir = argv[i++];
- }
- else
- {
- goto dispatch;
- }
- }
-
- if (bConsole)
- {
- // Install break handler, then run the C routine twice, once to setup, once to start running.
- SetConsoleCtrlHandler(&BreakHandler,TRUE);
- if ((i=real_main(1))!=0)
- {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");
- return i;
- }
- return real_main(0);
- }
- else if (lpszInstall)
- {
- CmdInstallService(lpszInstall);
- return 0;
- }
- else if (lpszRemove)
- {
- CmdRemoveService(lpszRemove);
- return 0;
- }
-
-
- // if it doesn't match any of the above parameters
- // the service control manager may be starting the service
- // so we must call StartServiceCtrlDispatcher
- dispatch:
- // this is just to be friendly
- printf("%s -install <name> to install the named service\n", argv[0]);
- printf("%s -remove <name> to remove the named service\n", argv[0]);
- printf("%s -console to run as a console app for debugging\n", argv[0]);
- printf("%s -check to run as a console app and check configuration\n", argv[0]);
- printf("\t-config <file> to specify the config file to use\n");
- printf("\t-schemadir <dir> to specify where schemas are\n");
- printf("\nService starting.\nThis may take several seconds. Please wait.\n" );
-
- SERVICE_TABLE_ENTRY dispatchTable[] =
- {
- { "SHIBD", (LPSERVICE_MAIN_FUNCTION)service_main },
- { NULL, NULL }
- };
-
- if (!StartServiceCtrlDispatcher(dispatchTable))
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "StartServiceCtrlDispatcher failed.");
- return 0;
-}
-
-//
-// FUNCTION: ServiceStart
-//
-// PURPOSE: Actual code of the service
-// that does the work.
-//
-VOID ServiceStart (DWORD dwArgc, LPSTR *lpszArgv)
-{
-
- if (real_main(1)!=0)
- {
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");
- return;
- }
-
- LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7700, NULL, "shibd started successfully.");
-
- if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0))
- return;
-
- real_main(0);
-}
-
-
-//
-// FUNCTION: ServiceStop
-//
-// PURPOSE: Stops the service
-//
-VOID ServiceStop()
-{
- if (!bConsole)
- LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "shibd stopping...");
- shibd_shutdown=true;
-}
-
-
-void WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv)
-{
-
- // register our service control handler:
- sshStatusHandle=RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl);
- if (!sshStatusHandle)
- goto cleanup;
-
- // SERVICE_STATUS members that don't change in example
- ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- ssStatus.dwServiceSpecificExitCode = 0;
-
-
- // report the status to the service control manager.
- if (!ReportStatusToSCMgr(
- SERVICE_START_PENDING, // service state
- NO_ERROR, // exit code
- 3000)) // wait hint
- goto cleanup;
-
-
- ServiceStart(dwArgc, lpszArgv);
-
-cleanup:
-
- // try to report the stopped status to the service control manager.
- //
- if (sshStatusHandle)
- (VOID)ReportStatusToSCMgr(
- SERVICE_STOPPED,
- dwErr,
- 0);
-
- return;
-}
-
-
-//
-// FUNCTION: service_ctrl
-//
-// PURPOSE: This function is called by the SCM whenever
-// ControlService() is called on this service.
-//
-// PARAMETERS:
-// dwCtrlCode - type of control requested
-//
-// RETURN VALUE:
-// none
-//
-VOID WINAPI service_ctrl(DWORD dwCtrlCode)
-{
- // Handle the requested control code.
- //
- switch(dwCtrlCode)
- {
- // Stop the service.
- //
- case SERVICE_CONTROL_STOP:
- ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
- ServiceStop();
- break;
-
- // Update the service status.
- //
- case SERVICE_CONTROL_INTERROGATE:
- break;
-
- // invalid control code
- //
- default:
- break;
-
- }
-
- ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
-}
-
-
-//
-// FUNCTION: ReportStatusToSCMgr()
-//
-// PURPOSE: Sets the current status of the service and
-// reports it to the Service Control Manager
-//
-// PARAMETERS:
-// dwCurrentState - the state of the service
-// dwWin32ExitCode - error code to report
-// dwWaitHint - worst case estimate to next checkpoint
-//
-// RETURN VALUE:
-// TRUE - success
-// FALSE - failure
-//
-BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
- DWORD dwWin32ExitCode,
- DWORD dwWaitHint)
-{
- static DWORD dwCheckPoint = 1;
- BOOL fResult = TRUE;
-
-
- if (!bConsole) // when console we don't report to the SCM
- {
- if (dwCurrentState == SERVICE_START_PENDING)
- ssStatus.dwControlsAccepted = 0;
- else
- ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
-
- ssStatus.dwCurrentState = dwCurrentState;
- ssStatus.dwWin32ExitCode = dwWin32ExitCode;
- ssStatus.dwWaitHint = dwWaitHint;
-
- if ( ( dwCurrentState == SERVICE_RUNNING ) ||
- ( dwCurrentState == SERVICE_STOPPED ) )
- ssStatus.dwCheckPoint = 0;
- else
- ssStatus.dwCheckPoint = dwCheckPoint++;
-
-
- // Report the status of the service to the service control manager.
- //
- if (!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus)))
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "SetServiceStatus failed.");
- }
- return fResult;
-}
-
-
-///////////////////////////////////////////////////////////////////
-//
-// The following code handles service installation and removal
-//
-//
-void CmdInstallService(LPCSTR name)
-{
- SC_HANDLE schService;
- SC_HANDLE schSCManager;
-
- char szPath[256];
- char dispName[512];
- char realName[512];
- char cmd[2048];
-
- if ( GetModuleFileName( NULL, szPath, 256 ) == 0 )
- {
- printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256));
- return;
- }
-
- sprintf(dispName,"Shibboleth %s Daemon (%s)",PACKAGE_VERSION,name);
- sprintf(realName,"shibd_%s",name);
- if (shar_config && shar_schemadir)
- sprintf(cmd,"%s -config %s -schemadir %s",szPath,shar_config,shar_schemadir);
- else if (shar_config)
- sprintf(cmd,"%s -config %s",szPath,shar_config);
- else if (shar_schemadir)
- sprintf(cmd,"%s -schemadir %s",szPath,shar_schemadir);
- else
- sprintf(cmd,"%s",szPath);
-
- schSCManager = OpenSCManager(
- NULL, // machine (NULL == local)
- NULL, // database (NULL == default)
- SC_MANAGER_ALL_ACCESS // access required
- );
-
-
- if ( schSCManager )
- {
- schService = CreateService(
- schSCManager, // SCManager database
- realName, // name of service
- dispName, // name to display
- SERVICE_ALL_ACCESS, // desired access
- SERVICE_WIN32_OWN_PROCESS, // service type
- SERVICE_AUTO_START, // start type
- SERVICE_ERROR_NORMAL, // error control type
- cmd, // service's command line
- NULL, // no load ordering group
- NULL, // no tag identifier
- NULL, // dependencies
- NULL, // LocalSystem account
- NULL); // no password
-
- if ( schService )
- {
- printf("%s installed.\n",realName);
- CloseServiceHandle(schService);
- }
- else
- {
- printf("CreateService failed - %s\n", GetLastErrorText(szErr, 256));
- }
-
- CloseServiceHandle(schSCManager);
- }
- else
- printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));
-}
-
-void CmdRemoveService(LPCSTR name)
-{
- SC_HANDLE schService;
- SC_HANDLE schSCManager;
- char realName[512];
-
- sprintf(realName,"shibd_%s",name);
-
- schSCManager = OpenSCManager(
- NULL, // machine (NULL == local)
- NULL, // database (NULL == default)
- SC_MANAGER_ALL_ACCESS // access required
- );
- if ( schSCManager )
- {
- schService = OpenService(schSCManager, realName, SERVICE_ALL_ACCESS);
-
- if (schService)
- {
- // try to stop the service
- if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
- {
- printf("Stopping shibd (%s).", name);
- Sleep( 1000 );
-
- while( QueryServiceStatus( schService, &ssStatus ) )
- {
- if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
- {
- printf(".");
- Sleep( 1000 );
- }
- else
- break;
- }
-
- if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
- printf("\n%s stopped.\n", realName);
- else
- printf("\n%s failed to stop.\n", realName);
-
- }
-
- // now remove the service
- if( DeleteService(schService) )
- printf("%s removed.\n", realName);
- else
- printf("DeleteService failed - %s\n", GetLastErrorText(szErr,256));
-
-
- CloseServiceHandle(schService);
- }
- else
- printf("OpenService failed - %s\n", GetLastErrorText(szErr,256));
-
- CloseServiceHandle(schSCManager);
- }
- else
- printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));
-}
-
-
-//
-// FUNCTION: GetLastErrorText
-//
-// PURPOSE: copies error message text to string
-//
-// PARAMETERS:
-// lpszBuf - destination buffer
-// dwSize - size of buffer
-//
-// RETURN VALUE:
-// destination buffer
-//
-// COMMENTS:
-//
-LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize )
-{
- DWORD dwRet;
- LPSTR lpszTemp = NULL;
-
- dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
- NULL,
- GetLastError(),
- LANG_NEUTRAL,
- (LPSTR)&lpszTemp,
- 0,
- NULL );
-
- // supplied buffer is not long enough
- if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )
- lpszBuf[0] = '\0';
- else
- {
- lpszTemp[lstrlen(lpszTemp)-2] = '\0'; //remove cr and newline character
- sprintf( lpszBuf, "%s (0x%x)", lpszTemp, GetLastError() );
- }
-
- if ( lpszTemp )
- LocalFree((HLOCAL) lpszTemp );
-
- return lpszBuf;
-}
-
-BOOL LogEvent(
- LPCSTR lpUNCServerName,
- WORD wType,
- DWORD dwEventID,
- PSID lpUserSid,
- LPCSTR message)
-{
- LPCSTR messages[] = {message, NULL};
-
- HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth Daemon");
- BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);
- return (DeregisterEventSource(hElog) && res);
-}
+/*\r
+ * Copyright 2001-2007 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/*\r
+ * shar_win32.cpp -- the SHAR "main" code on Win32\r
+ *\r
+ * Created By: Scott Cantor (cantor.2@osu.edu)\r
+ *\r
+ * $Id: shar_win32.cpp 2150 2007-02-02 04:06:15 +0000 (Fri, 02 Feb 2007) cantor $\r
+ */\r
+\r
+#include "config_win32.h"\r
+\r
+#define _CRT_NONSTDC_NO_DEPRECATE 1\r
+#define _CRT_SECURE_NO_DEPRECATE 1\r
+\r
+#include <shib-target/shib-target.h>\r
+\r
+extern bool shibd_shutdown; // signals shutdown to Unix side\r
+extern const char* shar_schemadir;\r
+extern const char* shar_config;\r
+extern bool shar_checkonly;\r
+\r
+// internal variables\r
+SERVICE_STATUS ssStatus; // current status of the service\r
+SERVICE_STATUS_HANDLE sshStatusHandle;\r
+DWORD dwErr = 0;\r
+BOOL bConsole = FALSE;\r
+char szErr[256];\r
+LPCSTR lpszInstall = NULL;\r
+LPCSTR lpszRemove = NULL;\r
+\r
+// internal function prototypes\r
+VOID WINAPI service_ctrl(DWORD dwCtrlCode);\r
+VOID WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv);\r
+VOID CmdInstallService(LPCSTR);\r
+VOID CmdRemoveService(LPCSTR);\r
+LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize );\r
+\r
+BOOL LogEvent(\r
+ LPCTSTR lpUNCServerName,\r
+ WORD wType,\r
+ DWORD dwEventID,\r
+ PSID lpUserSid,\r
+ LPCTSTR message);\r
+\r
+VOID ServiceStart(DWORD dwArgc, LPSTR *lpszArgv);\r
+VOID ServiceStop();\r
+BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);\r
+void AddToMessageLog(LPSTR lpszMsg);\r
+\r
+BOOL WINAPI BreakHandler(DWORD dwCtrlType)\r
+{\r
+ switch(dwCtrlType)\r
+ {\r
+ case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate\r
+ case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in console mode\r
+ ServiceStop();\r
+ return TRUE;\r
+ }\r
+ return FALSE;\r
+}\r
+\r
+\r
+int real_main(int); // The revised two-phase main() in shar.cpp\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+ int i=1;\r
+ while ((argc > i) && ((*argv[i] == '-') || (*argv[i] == '/')))\r
+ {\r
+ if (_stricmp("install", argv[i]+1) == 0)\r
+ {\r
+ if (argc > ++i)\r
+ lpszInstall = argv[i++];\r
+ }\r
+ else if (_stricmp("remove", argv[i]+1) == 0)\r
+ {\r
+ if (argc > ++i)\r
+ lpszRemove = argv[i++];\r
+ }\r
+ else if (_stricmp( "console", argv[i]+1) == 0)\r
+ {\r
+ i++;\r
+ bConsole = TRUE;\r
+ }\r
+ else if (_stricmp( "check", argv[i]+1) == 0)\r
+ {\r
+ i++;\r
+ bConsole = TRUE;\r
+ shar_checkonly=true;\r
+ }\r
+ else if (_stricmp( "config", argv[i]+1) == 0)\r
+ {\r
+ if (argc > ++i)\r
+ shar_config = argv[i++];\r
+ }\r
+ else if (_stricmp( "schemadir", argv[i]+1) == 0)\r
+ {\r
+ if (argc > ++i)\r
+ shar_schemadir = argv[i++];\r
+ }\r
+ else\r
+ {\r
+ goto dispatch;\r
+ }\r
+ }\r
+ \r
+ if (bConsole)\r
+ {\r
+ // Install break handler, then run the C routine twice, once to setup, once to start running.\r
+ SetConsoleCtrlHandler(&BreakHandler,TRUE);\r
+ if ((i=real_main(1))!=0)\r
+ {\r
+ LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");\r
+ return i;\r
+ }\r
+ return real_main(0);\r
+ }\r
+ else if (lpszInstall)\r
+ {\r
+ CmdInstallService(lpszInstall);\r
+ return 0;\r
+ }\r
+ else if (lpszRemove)\r
+ {\r
+ CmdRemoveService(lpszRemove);\r
+ return 0;\r
+ }\r
+ \r
+\r
+ // if it doesn't match any of the above parameters\r
+ // the service control manager may be starting the service\r
+ // so we must call StartServiceCtrlDispatcher\r
+ dispatch:\r
+ // this is just to be friendly\r
+ printf("%s -install <name> to install the named service\n", argv[0]);\r
+ printf("%s -remove <name> to remove the named service\n", argv[0]);\r
+ printf("%s -console to run as a console app for debugging\n", argv[0]);\r
+ printf("%s -check to run as a console app and check configuration\n", argv[0]);\r
+ printf("\t-config <file> to specify the config file to use\n");\r
+ printf("\t-schemadir <dir> to specify where schemas are\n");\r
+ printf("\nService starting.\nThis may take several seconds. Please wait.\n" );\r
+\r
+ SERVICE_TABLE_ENTRY dispatchTable[] =\r
+ {\r
+ { "SHIBD", (LPSERVICE_MAIN_FUNCTION)service_main },\r
+ { NULL, NULL }\r
+ };\r
+\r
+ if (!StartServiceCtrlDispatcher(dispatchTable))\r
+ LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "StartServiceCtrlDispatcher failed.");\r
+ return 0;\r
+}\r
+\r
+//\r
+// FUNCTION: ServiceStart\r
+//\r
+// PURPOSE: Actual code of the service\r
+// that does the work.\r
+//\r
+VOID ServiceStart (DWORD dwArgc, LPSTR *lpszArgv)\r
+{\r
+\r
+ if (real_main(1)!=0)\r
+ {\r
+ LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");\r
+ return;\r
+ }\r
+\r
+ LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7700, NULL, "shibd started successfully.");\r
+\r
+ if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0))\r
+ return;\r
+\r
+ real_main(0);\r
+}\r
+\r
+\r
+//\r
+// FUNCTION: ServiceStop\r
+//\r
+// PURPOSE: Stops the service\r
+//\r
+VOID ServiceStop()\r
+{\r
+ if (!bConsole)\r
+ LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "shibd stopping...");\r
+ shibd_shutdown=true;\r
+}\r
+\r
+\r
+void WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv)\r
+{\r
+\r
+ // register our service control handler:\r
+ sshStatusHandle=RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl);\r
+ if (!sshStatusHandle)\r
+ goto cleanup;\r
+\r
+ // SERVICE_STATUS members that don't change in example\r
+ ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;\r
+ ssStatus.dwServiceSpecificExitCode = 0;\r
+\r
+\r
+ // report the status to the service control manager.\r
+ if (!ReportStatusToSCMgr(\r
+ SERVICE_START_PENDING, // service state\r
+ NO_ERROR, // exit code\r
+ 3000)) // wait hint\r
+ goto cleanup;\r
+\r
+\r
+ ServiceStart(dwArgc, lpszArgv);\r
+\r
+cleanup:\r
+\r
+ // try to report the stopped status to the service control manager.\r
+ //\r
+ if (sshStatusHandle)\r
+ (VOID)ReportStatusToSCMgr(\r
+ SERVICE_STOPPED,\r
+ dwErr,\r
+ 0);\r
+\r
+ return;\r
+}\r
+\r
+\r
+//\r
+// FUNCTION: service_ctrl\r
+//\r
+// PURPOSE: This function is called by the SCM whenever\r
+// ControlService() is called on this service.\r
+//\r
+// PARAMETERS:\r
+// dwCtrlCode - type of control requested\r
+//\r
+// RETURN VALUE:\r
+// none\r
+//\r
+VOID WINAPI service_ctrl(DWORD dwCtrlCode)\r
+{\r
+ // Handle the requested control code.\r
+ //\r
+ switch(dwCtrlCode)\r
+ {\r
+ // Stop the service.\r
+ //\r
+ case SERVICE_CONTROL_STOP:\r
+ ssStatus.dwCurrentState = SERVICE_STOP_PENDING;\r
+ ServiceStop();\r
+ break;\r
+\r
+ // Update the service status.\r
+ //\r
+ case SERVICE_CONTROL_INTERROGATE:\r
+ break;\r
+\r
+ // invalid control code\r
+ //\r
+ default:\r
+ break;\r
+\r
+ }\r
+\r
+ ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);\r
+}\r
+\r
+\r
+//\r
+// FUNCTION: ReportStatusToSCMgr()\r
+//\r
+// PURPOSE: Sets the current status of the service and\r
+// reports it to the Service Control Manager\r
+//\r
+// PARAMETERS:\r
+// dwCurrentState - the state of the service\r
+// dwWin32ExitCode - error code to report\r
+// dwWaitHint - worst case estimate to next checkpoint\r
+//\r
+// RETURN VALUE:\r
+// TRUE - success\r
+// FALSE - failure\r
+//\r
+BOOL ReportStatusToSCMgr(DWORD dwCurrentState,\r
+ DWORD dwWin32ExitCode,\r
+ DWORD dwWaitHint)\r
+{\r
+ static DWORD dwCheckPoint = 1;\r
+ BOOL fResult = TRUE;\r
+\r
+\r
+ if (!bConsole) // when console we don't report to the SCM\r
+ {\r
+ if (dwCurrentState == SERVICE_START_PENDING)\r
+ ssStatus.dwControlsAccepted = 0;\r
+ else\r
+ ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;\r
+\r
+ ssStatus.dwCurrentState = dwCurrentState;\r
+ ssStatus.dwWin32ExitCode = dwWin32ExitCode;\r
+ ssStatus.dwWaitHint = dwWaitHint;\r
+\r
+ if ( ( dwCurrentState == SERVICE_RUNNING ) ||\r
+ ( dwCurrentState == SERVICE_STOPPED ) )\r
+ ssStatus.dwCheckPoint = 0;\r
+ else\r
+ ssStatus.dwCheckPoint = dwCheckPoint++;\r
+\r
+\r
+ // Report the status of the service to the service control manager.\r
+ //\r
+ if (!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus)))\r
+ LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "SetServiceStatus failed.");\r
+ }\r
+ return fResult;\r
+}\r
+\r
+\r
+///////////////////////////////////////////////////////////////////\r
+//\r
+// The following code handles service installation and removal\r
+//\r
+//\r
+void CmdInstallService(LPCSTR name)\r
+{\r
+ SC_HANDLE schService;\r
+ SC_HANDLE schSCManager;\r
+\r
+ char szPath[256];\r
+ char dispName[512];\r
+ char realName[512];\r
+ char cmd[2048];\r
+\r
+ if ( GetModuleFileName( NULL, szPath, 256 ) == 0 )\r
+ {\r
+ printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256));\r
+ return;\r
+ }\r
+ \r
+ sprintf(dispName,"Shibboleth %s Daemon (%s)",PACKAGE_VERSION,name);\r
+ sprintf(realName,"shibd_%s",name);\r
+ if (shar_config && shar_schemadir)\r
+ sprintf(cmd,"%s -config %s -schemadir %s",szPath,shar_config,shar_schemadir);\r
+ else if (shar_config)\r
+ sprintf(cmd,"%s -config %s",szPath,shar_config);\r
+ else if (shar_schemadir)\r
+ sprintf(cmd,"%s -schemadir %s",szPath,shar_schemadir);\r
+ else\r
+ sprintf(cmd,"%s",szPath);\r
+\r
+ schSCManager = OpenSCManager(\r
+ NULL, // machine (NULL == local)\r
+ NULL, // database (NULL == default)\r
+ SC_MANAGER_ALL_ACCESS // access required\r
+ );\r
+ \r
+ \r
+ if ( schSCManager )\r
+ {\r
+ schService = CreateService(\r
+ schSCManager, // SCManager database\r
+ realName, // name of service\r
+ dispName, // name to display\r
+ SERVICE_ALL_ACCESS, // desired access\r
+ SERVICE_WIN32_OWN_PROCESS, // service type\r
+ SERVICE_AUTO_START, // start type\r
+ SERVICE_ERROR_NORMAL, // error control type\r
+ cmd, // service's command line\r
+ NULL, // no load ordering group\r
+ NULL, // no tag identifier\r
+ NULL, // dependencies\r
+ NULL, // LocalSystem account\r
+ NULL); // no password\r
+\r
+ if ( schService )\r
+ {\r
+ printf("%s installed.\n",realName);\r
+ CloseServiceHandle(schService);\r
+ }\r
+ else\r
+ {\r
+ printf("CreateService failed - %s\n", GetLastErrorText(szErr, 256));\r
+ }\r
+\r
+ CloseServiceHandle(schSCManager);\r
+ }\r
+ else\r
+ printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));\r
+}\r
+\r
+void CmdRemoveService(LPCSTR name)\r
+{\r
+ SC_HANDLE schService;\r
+ SC_HANDLE schSCManager;\r
+ char realName[512];\r
+\r
+ sprintf(realName,"shibd_%s",name);\r
+\r
+ schSCManager = OpenSCManager(\r
+ NULL, // machine (NULL == local)\r
+ NULL, // database (NULL == default)\r
+ SC_MANAGER_ALL_ACCESS // access required\r
+ );\r
+ if ( schSCManager )\r
+ {\r
+ schService = OpenService(schSCManager, realName, SERVICE_ALL_ACCESS);\r
+\r
+ if (schService)\r
+ {\r
+ // try to stop the service\r
+ if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )\r
+ {\r
+ printf("Stopping shibd (%s).", name);\r
+ Sleep( 1000 );\r
+\r
+ while( QueryServiceStatus( schService, &ssStatus ) )\r
+ {\r
+ if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )\r
+ {\r
+ printf(".");\r
+ Sleep( 1000 );\r
+ }\r
+ else\r
+ break;\r
+ }\r
+\r
+ if ( ssStatus.dwCurrentState == SERVICE_STOPPED )\r
+ printf("\n%s stopped.\n", realName);\r
+ else\r
+ printf("\n%s failed to stop.\n", realName);\r
+\r
+ }\r
+\r
+ // now remove the service\r
+ if( DeleteService(schService) )\r
+ printf("%s removed.\n", realName);\r
+ else\r
+ printf("DeleteService failed - %s\n", GetLastErrorText(szErr,256));\r
+\r
+\r
+ CloseServiceHandle(schService);\r
+ }\r
+ else\r
+ printf("OpenService failed - %s\n", GetLastErrorText(szErr,256));\r
+\r
+ CloseServiceHandle(schSCManager);\r
+ }\r
+ else\r
+ printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));\r
+}\r
+\r
+\r
+//\r
+// FUNCTION: GetLastErrorText\r
+//\r
+// PURPOSE: copies error message text to string\r
+//\r
+// PARAMETERS:\r
+// lpszBuf - destination buffer\r
+// dwSize - size of buffer\r
+//\r
+// RETURN VALUE:\r
+// destination buffer\r
+//\r
+// COMMENTS:\r
+//\r
+LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize )\r
+{\r
+ DWORD dwRet;\r
+ LPSTR lpszTemp = NULL;\r
+\r
+ dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,\r
+ NULL,\r
+ GetLastError(),\r
+ LANG_NEUTRAL,\r
+ (LPSTR)&lpszTemp,\r
+ 0,\r
+ NULL );\r
+\r
+ // supplied buffer is not long enough\r
+ if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )\r
+ lpszBuf[0] = '\0';\r
+ else\r
+ {\r
+ lpszTemp[lstrlen(lpszTemp)-2] = '\0'; //remove cr and newline character\r
+ sprintf( lpszBuf, "%s (0x%x)", lpszTemp, GetLastError() );\r
+ }\r
+\r
+ if ( lpszTemp )\r
+ LocalFree((HLOCAL) lpszTemp );\r
+\r
+ return lpszBuf;\r
+}\r
+\r
+BOOL LogEvent(\r
+ LPCSTR lpUNCServerName,\r
+ WORD wType,\r
+ DWORD dwEventID,\r
+ PSID lpUserSid,\r
+ LPCSTR message)\r
+{\r
+ LPCSTR messages[] = {message, NULL};\r
+ \r
+ HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth Daemon");\r
+ BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);\r
+ return (DeregisterEventSource(hElog) && res);\r
+}\r