windows-nt/Source/XPSP1/NT/ds/netapi/svcctrl/client/svcstub.c

605 lines
17 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1991-1992 Microsoft Corporation
Module Name:
SvcStub.c (was scstub.c)
Abstract:
These are the Service Controller API RPC client stubs.
These stubs contain RPC work-around code due to the fact that RPC
does not support unions yet. Therefore, a remote entry point must be
created for every info-level. This results in messy looking switch
statements that are used to determine which entry point to call.
These switch statements include default paths that can currently cause
an error. When unions are available, the case statements will be
removed, and this side of the API will not make any assumptions as to
what a valid info level is for a given API.
Author:
Dan Lafferty (danl) 06-Feb-1991
Environment:
User Mode - Win32
Revision History:
06-Feb-1991 Danl
Created
12-Sep-1991 JohnRo
Downlevel NetService APIs.
06-Nov-1991 JohnRo
RAID 4186: Fix assert in RxNetShareAdd and other MIPS problems.
Use NetpRpcStatusToApiStatus, not NetpNtStatusToApiStatus.
Make sure API name is in every debug message.
08-Nov-1991 JohnRo
RAID 4186: assert in RxNetShareAdd and other DLL stub problems.
30-Mar-1992 JohnRo
Extracted DanL's code from /nt/private project back to NET project.
29-Apr-1992 JohnRo
Use FORMAT_ equates where possible.
08-May-1992 JohnRo
Translate service names on the fly.
14-May-1992 JohnRo
winsvc.h and related file cleanup.
06-Aug-1992 JohnRo
RAID 3021: NetService APIs don't always translate svc names.
09-Sep-1992 JohnRo
RAID 1090: net start/stop "" causes assertion.
Oops, NetServiceControl forgot to translate one more svc name.
05-Nov-1992 JohnRo
RAID 7780: Corrected error code for invalid level.
Also fixed overactive assert in NetServiceEnum with no services.
Also fixed rare memory leaks.
--*/
//
// INCLUDES
//
#define NOSERVICE // Avoid <winsvc.h> vs. <lmsvc.h> conflicts.
#include <windows.h> // DWORD, etc.
#include <lmcons.h> // NET_API_STATUS
#include <rpcutil.h> // NetRpc utils, GENERIC_ENUM_STRUC, etc.
#include <netdebug.h> // Needed by NetRpc.h; FORMAT_ equates.
#include <lmapibuf.h> // NetApiBufferAllocate(), etc.
#include <lmerr.h> // NetError codes
#include <lmremutl.h> // NetRemoteComputerSupports(), SUPPORTS_RPC
#include <lmsvc.h>
#include <rxsvc.h> // RxNetService routines.
#include <netlib.h> // NetpTranslateServiceName().
#include <svcdebug.h> // SCC_LOG
#include <svcmap.h> // MapService() routines.
//
// Globals
//
#ifdef SC_DEBUG
DWORD SvcctrlDebugLevel = DEBUG_ALL;
#else
DWORD SvcctrlDebugLevel = DEBUG_ERROR;
#endif
DBGSTATIC BOOL
MachineSupportsNt(
IN LPWSTR UncServerName OPTIONAL
);
NET_API_STATUS NET_API_FUNCTION
NetServiceControl (
IN LPCWSTR servername OPTIONAL,
IN LPCWSTR service,
IN DWORD opcode,
IN DWORD arg,
OUT LPBYTE *bufptr
)
/*++
Routine Description:
This is the DLL entrypoint for NetServiceControl.
Arguments:
servername - Pointer to a string containing the name of the computer
that is to execute the API function.
service - Pointer to a string containing the name of the service
that is to receive the control request.
opcode - The control request code.
arg - An additional (user defined) code that will be passed to the
service.
bufptr - pointer to a location where the service status is to
be returned. If this pointer is invalid, it will be set to NULL
upon return.
Return Value:
The returned InfoStruct2 structure is valid as long as the returned
error is NOT NERR_ServiceNotInstalled or NERR_ServiceBadServiceName.
NERR_Success - The operation was successful.
NERR_InternalError - LocalAlloc or TransactNamedPipe failed, or
TransactNamedPipe returned fewer bytes than expected.
NERR_ServiceNotInstalled - The service record was not found in the
installed list.
NERR_BadServiceName - The service name pointer was NULL.
NERR_ServiceCtlTimeout - The service did not respond with a status
message within the fixed timeout limit (RESPONSE_WAIT_TIMEOUT).
NERR_ServiceKillProcess - The service process had to be killed because
it wouldn't terminate when requested.
NERR_ServiceNotCtrl - The service cannot accept control messages.
The install state indicates that start-up or shut-down is pending.
NERR_ServiceCtrlNotValid - The request is not valid for this service.
For instance, a PAUSE request is not valid for a service that
lists itself as NOT_PAUSABLE.
ERROR_ACCESS_DENIED - This is a status response from the service
security check.
--*/
{
NET_API_STATUS apiStatus;
LPWSTR translatedServiceName;
LPBYTE untranslatedBuffer = NULL;
if (MachineSupportsNt( (LPWSTR) servername )) {
apiStatus = NetpTranslateServiceName(
(LPWSTR) service, // untranslated.
TRUE, // yes, we want new style name
& translatedServiceName );
NetpAssert( apiStatus == NO_ERROR );
apiStatus = MapServiceControl (
(LPWSTR) servername,
(LPWSTR) service,
opcode,
arg,
& untranslatedBuffer);
} else {
apiStatus = NetpTranslateServiceName(
(LPWSTR) service, // untranslated.
FALSE, // no, we don't want new style name
& translatedServiceName );
NetpAssert( apiStatus == NO_ERROR );
//
// Call downlevel...
//
apiStatus = RxNetServiceControl(
(LPWSTR) servername,
translatedServiceName,
opcode,
arg,
& untranslatedBuffer);
}
//
// Translate service name in returned buffer.
//
if (apiStatus == NO_ERROR) {
NetpAssert( untranslatedBuffer != NULL );
apiStatus = NetpTranslateNamesInServiceArray(
2, // level 2 by definition
untranslatedBuffer,
1, // only one entry
TRUE, // yes, caller wants new style names
(LPVOID *) (LPVOID) bufptr);
}
if (untranslatedBuffer != NULL) {
(VOID) NetApiBufferFree( untranslatedBuffer );
}
return(apiStatus);
}
NET_API_STATUS NET_API_FUNCTION
NetServiceEnum (
IN LPCWSTR servername OPTIONAL,
IN DWORD level,
OUT LPBYTE *bufptr,
IN DWORD prefmaxlen,
OUT LPDWORD entriesread,
OUT LPDWORD totalentries,
IN OUT LPDWORD resume_handle OPTIONAL
)
/*++
Routine Description:
This is the DLL entrypoint for NetSeviceEnum.
Arguments:
servername - Pointer to a string containing the name of the computer
that is to execute the API function.
level - This indicates the level of information that is desired.
bufptr - A pointer to the location where the pointer to the returned
array of info structures is to be placed.
prefmaxlen - Indicates a maximum size limit that the caller will allow
for the return buffer.
entriesread - A pointer to the location where the number of entries
(data structures)read is to be returned.
totalentries - A pointer to the location which upon return indicates
the total number of entries in the "active" database.
resumehandle - Pointer to a value that indicates where to resume
enumerating data.
Return Value:
Nerr_Success - The operation was successful.
ERROR_MORE_DATA - Not all of the data in the active database could be
returned.
ERROR_INVALID_LEVEL - An illegal info Level was passed in.
Note:
--*/
{
NET_API_STATUS apiStatus;
LPBYTE untranslatedBuffer = NULL;
if (MachineSupportsNt( (LPWSTR) servername )) {
apiStatus = MapServiceEnum (
(LPWSTR) servername,
level,
& untranslatedBuffer,
prefmaxlen,
entriesread,
totalentries,
resume_handle);
} else {
//
// Call downlevel...
//
apiStatus = RxNetServiceEnum(
(LPWSTR) servername,
level,
& untranslatedBuffer,
prefmaxlen,
entriesread,
totalentries,
resume_handle);
}
//
// Translate service names in returned buffer.
//
if ( (apiStatus == NO_ERROR) || (apiStatus == ERROR_MORE_DATA) ) {
if ( (*entriesread) > 0 ) { // One or more services returned.
NetpAssert( untranslatedBuffer != NULL );
NetpAssert( (*totalentries) > 0 );
apiStatus = NetpTranslateNamesInServiceArray(
level,
untranslatedBuffer,
*entriesread,
TRUE, // yes, caller wants new style names
(LPVOID *) (LPVOID) bufptr);
} else { // Zero services returned.
NetpAssert( untranslatedBuffer == NULL );
// Note: total entries may be > 0, if this is ERROR_MORE_DATA...
*bufptr = NULL;
}
}
if (untranslatedBuffer != NULL) {
(VOID) NetApiBufferFree( untranslatedBuffer );
}
return(apiStatus);
} // NetServiceEnum
NET_API_STATUS NET_API_FUNCTION
NetServiceGetInfo (
IN LPCWSTR servername OPTIONAL,
IN LPCWSTR service,
IN DWORD level,
OUT LPBYTE *bufptr
)
/*++
Routine Description:
This is the DLL entrypoint for NetServiceGetInfo.
Arguments:
servername - Pointer to a string containing the name of the computer
that is to execute the API function. Since this function is
executing on that computer, this information is not useful
by the time it gets here. It is really only useful on the RPC
client side.
service - Pointer to a string containing the name of the service
for which information is desired.
level - This indicates the level of information that is desired.
bufptr - Pointer to a Location where the pointer to the returned
information structure is to be placed.
Return Value:
NERR_Success - The operation was successful.
NERR_ServiceNotInstalled - if the service record was not found in
either the installed or uninstalled lists.
NERR_BadServiceName - The service name pointer was NULL.
ERROR_INVALID_LEVEL - An illegal info level was passed in.
ERROR_NOT_ENOUGH_MEMORY - The memory allocation for the returned
Info Record failed.
other - Any error returned by the following base API:
RPC Runtime API
--*/
{
NET_API_STATUS apiStatus;
LPWSTR translatedServiceName;
LPBYTE untranslatedBuffer = NULL;
if (MachineSupportsNt( (LPWSTR) servername )) {
apiStatus = NetpTranslateServiceName(
(LPWSTR) service, // untranslated.
TRUE, // yes, we want new style name
& translatedServiceName );
NetpAssert( apiStatus == NO_ERROR );
apiStatus = MapServiceGetInfo (
(LPWSTR) servername,
(LPWSTR) service,
level,
& untranslatedBuffer);
} else {
apiStatus = NetpTranslateServiceName(
(LPWSTR) service, // untranslated.
FALSE, // no, we don't want new style name
& translatedServiceName );
NetpAssert( apiStatus == NO_ERROR );
//
// Call downlevel...
//
apiStatus = RxNetServiceGetInfo(
(LPWSTR) servername,
translatedServiceName,
level,
& untranslatedBuffer);
}
//
// Translate service name in returned buffer.
//
if (apiStatus == NO_ERROR) {
NetpAssert( untranslatedBuffer != NULL );
apiStatus = NetpTranslateNamesInServiceArray(
level,
untranslatedBuffer,
1, // only one entry
TRUE, // yes, caller wants new style names
(LPVOID *) (LPVOID) bufptr);
}
if (untranslatedBuffer != NULL) {
(VOID) NetApiBufferFree( untranslatedBuffer );
}
return(apiStatus);
}
NET_API_STATUS NET_API_FUNCTION
NetServiceInstall (
IN LPCWSTR servername OPTIONAL,
IN LPCWSTR service,
IN DWORD argc,
IN LPCWSTR argv[],
OUT LPBYTE *bufptr
)
/*++
Routine Description:
This is the DLL entrypoint for NetServiceInstall.
Arguments:
servername - Points to a string containing the name of the computer
that is to execute the API function.
service- Points to a string containing the name of the service
that is to be started.
argc - Indicates the number or argument vectors in argv.
argv - A pointer to an array of pointers to strings. These
are command line arguments that are to be passed to the service.
bufptr - This is the address where a pointer to the service's
information buffer (SERVICE_INFO_2) is to be placed.
Return Value:
NERR_Success - The operation was successful
NERR_InternalError - There is a bug in this program somewhere.
NERR_ServiceInstalled - The service is already running - we do not
yet allow multiple instances of the same service.
NERR_CfgCompNotFound - The configuration component could not be found.
The Image File could not be found for this service.
NERR_ServiceTableFull - The maximum number of running services has
already been reached.
NERR_ServiceCtlTimeout - The service program did not respond to the
start-up request within the timeout period. If this was the
only service in the service process, the service process was
killed.
ERROR_NOT_ENOUGH_MEMORY - If this error occurs early in the
start-up procedure, the start-up will fail. If it occurs at the
end (allocating the return status buffer), the service will still
be started and allowed to run.
other - Any error returned by the following base API:
CreateNamedPipe
ConnectNamedPipe
CreateProcess
TransactNamedPipe
RPC Runtime API
--*/
{
NET_API_STATUS apiStatus;
LPWSTR translatedServiceName;
LPBYTE untranslatedBuffer = NULL;
if (MachineSupportsNt( (LPWSTR) servername )) {
apiStatus = NetpTranslateServiceName(
(LPWSTR) service, // untranslated.
TRUE, // yes, we want new style name
& translatedServiceName );
NetpAssert( apiStatus == NO_ERROR );
apiStatus = MapServiceInstall (
(LPWSTR) servername,
(LPWSTR) service,
argc,
(LPWSTR *) argv,
& untranslatedBuffer);
} else {
apiStatus = NetpTranslateServiceName(
(LPWSTR) service, // untranslated.
FALSE, // no, we don't want new style name
& translatedServiceName );
NetpAssert( apiStatus == NO_ERROR );
//
// Call downlevel....
//
apiStatus = RxNetServiceInstall(
(LPWSTR) servername,
translatedServiceName,
argc,
(LPWSTR *) argv,
& untranslatedBuffer);
}
//
// Translate service name in returned buffer.
//
if (apiStatus == NO_ERROR) {
NetpAssert( untranslatedBuffer != NULL );
apiStatus = NetpTranslateNamesInServiceArray(
2, // level 2 by definition
untranslatedBuffer,
1, // only one entry
TRUE, // yes, caller wants new style names
(LPVOID *) (LPVOID) bufptr);
}
if (untranslatedBuffer != NULL) {
(VOID) NetApiBufferFree( untranslatedBuffer );
}
return(apiStatus);
}
DBGSTATIC BOOL
MachineSupportsNt(
IN LPWSTR UncServerName OPTIONAL
)
{
NET_API_STATUS ApiStatus;
DWORD ActualSupports;
ApiStatus = NetRemoteComputerSupports(
UncServerName,
SUPPORTS_RPC, // Set SUPPORT_ bits wanted.
& ActualSupports );
if (ApiStatus != NO_ERROR) {
return (FALSE); // Error; say it doesn't support NT, and someone else
// will set the correct error code.
}
if (ActualSupports & SUPPORTS_RPC) {
return (TRUE);
}
return (FALSE);
} // MachineSupportsNt