-/*\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 <shibsp/base.h>\r
-#include <windows.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( "catalogs", 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-catalogs <dir> to specify schema catalogs\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
+/*
+ * 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: shar_win32.cpp 2150 2007-02-02 04:06:15 +0000 (Fri, 02 Feb 2007) cantor $
+ */
+
+#include "config_win32.h"
+
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+
+#include <shibsp/base.h>
+#include <string>
+#include <windows.h>
+
+using namespace std;
+
+extern bool shibd_shutdown; // signals shutdown to Unix side
+extern const char* shar_schemadir;
+extern const char* shar_config;
+extern const char* shar_prefix;
+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( "prefix", argv[i]+1) == 0)
+ {
+ if (argc > ++i)
+ shar_prefix = argv[i++];
+ }
+ else if (_stricmp( "catalogs", 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-prefix <dir> to specify the installation directory\n");
+ printf("\t-config <file> to specify the config file to use\n");
+ printf("\t-catalogs <catalog1:catalog2> to specify schema catalogs\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];
+
+ if ( GetModuleFileName( NULL, szPath, 256 ) == 0 )
+ {
+ printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256));
+ return;
+ }
+
+ string dispName = string("Shibboleth 2 Daemon (") + name + ")";
+ string realName = string("shibd_") + name;
+ string cmd(szPath);
+ if (shar_prefix)
+ cmd = cmd + " -prefix " + shar_prefix;
+ if (shar_config)
+ cmd = cmd + " -config " + shar_config;
+ if (shar_schemadir)
+ cmd = cmd + " -schemadir " + shar_schemadir;
+
+ schSCManager = OpenSCManager(
+ NULL, // machine (NULL == local)
+ NULL, // database (NULL == default)
+ SC_MANAGER_ALL_ACCESS // access required
+ );
+
+
+ if ( schSCManager )
+ {
+ schService = CreateService(
+ schSCManager, // SCManager database
+ realName.c_str(), // name of service
+ dispName.c_str(), // 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.c_str(), // 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.c_str());
+ 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];
+
+ _snprintf(realName,sizeof(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);
+}