/* File service.c Handles requests to deal with the remote access service as neccessary for the dialup-server ui. Paul Mayfield, 11/3/97 */ #include "rassrv.h" // Data used for the dialup server typedef struct _SERVICE_DATA { HANDLE hSC; HANDLE hService; SERVICE_STATUS Status; } SERVICE_DATA; // This is the string that holds the name of the remote access service static WCHAR pszRemoteAccess[] = L"remoteaccess"; static WCHAR pszRasman[] = L"rasman"; static WCHAR pszServer[] = L"lanmanserver"; // Opens a named dialup service object // DWORD DialupOpenNamedService( IN WCHAR* pszService, OUT HANDLE * phDialup) { SERVICE_DATA * pServData; BOOL bOk = FALSE; DWORD dwErr = NO_ERROR; // Validate parameters if (!phDialup) { return ERROR_INVALID_PARAMETER; } // Create the data structure if ((pServData = RassrvAlloc(sizeof(SERVICE_DATA), TRUE)) == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } do { // Open the service manager pServData->hSC = OpenSCManager( NULL, SERVICES_ACTIVE_DATABASE, GENERIC_EXECUTE); if (! pServData->hSC) { dwErr = GetLastError(); break; } // Open the dialup service pServData->hService = OpenServiceW( pServData->hSC, pszService, SERVICE_START | SERVICE_STOP | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS); if (! pServData->hService) { dwErr = GetLastError(); break; } // Assign the handle *phDialup = (HANDLE)pServData; bOk = TRUE; } while (FALSE); // Cleanup { if (! bOk) { if (pServData->hService) { CloseServiceHandle(pServData->hService); } if (pServData->hSC) { CloseServiceHandle(pServData->hSC); } RassrvFree(pServData); *phDialup = NULL; } } return NO_ERROR; } // Opens a reference to the server service object DWORD SvcOpenServer(HANDLE * phDialup) { return DialupOpenNamedService(pszServer, phDialup); } // Opens a reference to the rasman service object DWORD SvcOpenRasman(HANDLE * phDialup) { return DialupOpenNamedService(pszRasman, phDialup); } // Creates/destroys instances of the dialup server service object DWORD SvcOpenRemoteAccess(HANDLE * phDialup) { return DialupOpenNamedService(pszRemoteAccess, phDialup); } // Close up the references to the dialup service object DWORD SvcClose(HANDLE hDialup) { SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup; if (! pServData) return ERROR_INVALID_PARAMETER; if (pServData->hService) CloseServiceHandle(pServData->hService); if (pServData->hSC) CloseServiceHandle(pServData->hSC); RassrvFree(pServData); return NO_ERROR; } // Gets the status of a dialup server service object. DWORD SvcIsStarted (HANDLE hDialup, PBOOL pbStarted) { SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup; BOOL bOk; // Verify parameters if (!pServData || !pbStarted) return ERROR_INVALID_PARAMETER; // Get the status bOk = QueryServiceStatus (pServData->hService, &pServData->Status); if (! bOk) return GetLastError(); // Return the status *pbStarted = (BOOL)(pServData->Status.dwCurrentState == SERVICE_RUNNING); return NO_ERROR; } // Gets the status of a dialup server service object. DWORD SvcIsStopped (HANDLE hDialup, PBOOL pbStopped) { SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup; BOOL bOk; // Verify parameters if (!pServData || !pbStopped) return ERROR_INVALID_PARAMETER; // Get the status bOk = QueryServiceStatus (pServData->hService, &pServData->Status); if (! bOk) return GetLastError(); // Return the status *pbStopped = (BOOL)(pServData->Status.dwCurrentState == SERVICE_STOPPED); return NO_ERROR; } // Gets the status of a dialup server service object. DWORD SvcIsPaused (HANDLE hDialup, PBOOL pbPaused) { SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup; BOOL bOk; // Verify parameters if (!pServData || !pbPaused) return ERROR_INVALID_PARAMETER; // Get the status bOk = QueryServiceStatus (pServData->hService, &pServData->Status); if (! bOk) return GetLastError(); // Return the status *pbPaused = (BOOL)(pServData->Status.dwCurrentState == SERVICE_PAUSED); return NO_ERROR; } // // Returns whether the given state is a pending state // BOOL DialupIsPendingState (DWORD dwState) { return (BOOL) ((dwState == SERVICE_START_PENDING) || (dwState == SERVICE_STOP_PENDING) || (dwState == SERVICE_CONTINUE_PENDING) || (dwState == SERVICE_PAUSE_PENDING) ); } // Gets the status of a dialup server service object. DWORD SvcIsPending (HANDLE hDialup, PBOOL pbPending) { SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup; BOOL bOk; // Verify parameters if (!pServData || !pbPending) return ERROR_INVALID_PARAMETER; // Get the status bOk = QueryServiceStatus (pServData->hService, &pServData->Status); if (! bOk) return GetLastError(); // Return the status *pbPending = DialupIsPendingState (pServData->Status.dwCurrentState); return NO_ERROR; } // Start and stop the service. Both functions block until the service // completes startup/stop or until dwTimeout (in seconds) expires. DWORD SvcStart(HANDLE hDialup, DWORD dwTimeout) { SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup; DWORD dwErr, dwState; BOOL bStarted, bOk; // See if we're already started if ((dwErr = SvcIsStarted(hDialup, &bStarted)) != NO_ERROR) return dwErr; if (bStarted) return NO_ERROR; // Put the service in a state that so that // it is trying to start. (continue if paused, // start if stopped) dwState = pServData->Status.dwCurrentState; switch (dwState) { case SERVICE_STOPPED: bOk = StartService(pServData->hService, 0, NULL); if (! bOk) return GetLastError(); break; case SERVICE_PAUSED: bOk = ControlService(pServData->hService, SERVICE_CONTROL_CONTINUE, &(pServData->Status)); if (! bOk) return GetLastError(); break; } // Wait for the service to change states or for the timeout to // expire. while (dwTimeout != 0) { // Wait for something to happen Sleep(1000); dwTimeout--; // Get the status of the service bOk = QueryServiceStatus (pServData->hService, &(pServData->Status)); if (! bOk) return GetLastError(); // See if the state changed if (dwState != pServData->Status.dwCurrentState) { // If the service changed to a pending state, continue if (DialupIsPendingState (pServData->Status.dwCurrentState)) dwState = pServData->Status.dwCurrentState; // Otherwise, we're either stopped or running else break; } } // Return a timeout error if appropriate if (dwTimeout == 0) return ERROR_TIMEOUT; // If the service is now running, then everything if (pServData->Status.dwCurrentState == SERVICE_RUNNING) return NO_ERROR; // Otherwise, return the fact that we were'nt able to // get to a running state if (pServData->Status.dwWin32ExitCode != NO_ERROR) return pServData->Status.dwWin32ExitCode; return ERROR_CAN_NOT_COMPLETE; } // Stops the service. DWORD SvcStop(HANDLE hDialup, DWORD dwTimeout) { SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup; DWORD dwErr, dwState; BOOL bStopped, bOk; // See if we're already stopped if ((dwErr = SvcIsStopped(hDialup, &bStopped)) != NO_ERROR) return dwErr; if (bStopped) return NO_ERROR; // Stop the service dwState = pServData->Status.dwCurrentState; bOk = ControlService(pServData->hService, SERVICE_CONTROL_STOP, &pServData->Status); if (! bOk) return GetLastError(); // Wait for the service to change states or for the timeout to // expire. while (dwTimeout != 0) { // Wait for something to happen Sleep(1000); dwTimeout--; // Get the status of the service bOk = QueryServiceStatus (pServData->hService, &(pServData->Status)); if (! bOk) return GetLastError(); // See if the state changed if (dwState != pServData->Status.dwCurrentState) { // If the service changed to a pending state, continue if (DialupIsPendingState (pServData->Status.dwCurrentState)) dwState = pServData->Status.dwCurrentState; // Otherwise, we're either stopped or running else break; } } // Report a timeout if (dwTimeout == 0) return ERROR_TIMEOUT; // If the service is now stopped, then everything is great if (pServData->Status.dwCurrentState == SERVICE_STOPPED) return NO_ERROR; // Otherwise report that we're unable to stop the service return ERROR_CAN_NOT_COMPLETE; } // Marks the dialup service as autostart DWORD SvcMarkAutoStart(HANDLE hDialup) { SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup; BOOL bOk; // Validate the parameters if (! pServData) return ERROR_INVALID_PARAMETER; // Stop the service bOk = ChangeServiceConfig(pServData->hService, SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (! bOk) return GetLastError(); return NO_ERROR; } // Marks the service as disabled. DWORD SvcMarkDisabled(HANDLE hDialup) { SERVICE_DATA * pServData = (SERVICE_DATA *)hDialup; BOOL bOk; // Validate the parameters if (! pServData) return ERROR_INVALID_PARAMETER; // Stop the service bOk = ChangeServiceConfig(pServData->hService, SERVICE_NO_CHANGE, SERVICE_DISABLED, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (! bOk) return GetLastError(); return NO_ERROR; }