windows-nt/Source/XPSP1/NT/net/rras/ras/ui/rassrvui/service.c
2020-09-26 16:20:57 +08:00

405 lines
11 KiB
C

/*
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;
}