Renamed shar project, some Makefile fixes.
[shibboleth/sp.git] / shibd / shibd_win32.cpp
similarity index 96%
rename from shar/shar_win32.cpp
rename to shibd/shibd_win32.cpp
index c9043ea..fc48dbc 100644 (file)
-/*
- *  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