mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1557 lines
39 KiB
1557 lines
39 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
SCANSI.CXX
|
|
|
|
Abstract:
|
|
|
|
This file contains ansi wrappers for the Service Controller API
|
|
functions.
|
|
|
|
Author:
|
|
|
|
Dan Lafferty (danl) 04-Feb-1992
|
|
|
|
Environment:
|
|
|
|
User Mode - Win32
|
|
|
|
Revision History:
|
|
|
|
05-Nov-1992 Danl
|
|
Added DisplayName Changes & new API.
|
|
28-May-1992 JohnRo
|
|
RAID 9829: winsvc.h and related file cleanup.
|
|
14-Apr-1992 JohnRo
|
|
We should not return password from any of our APIs.
|
|
04-Feb-1992 danl
|
|
Created
|
|
|
|
--*/
|
|
|
|
#include "precomp.hxx"
|
|
#include <sclib.h> // ScConvertToUnicode, ScConvertToAnsi
|
|
#include <scwow.h> // 32/64-bit interop structures
|
|
|
|
|
|
DWORD
|
|
ROpenSCManagerA(
|
|
IN LPSTR lpMachineName,
|
|
IN LPSTR lpDatabaseName OPTIONAL,
|
|
IN DWORD dwDesiredAccess,
|
|
OUT LPSC_RPC_HANDLE lpScHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
lpMachineName -
|
|
|
|
lpDatabaseName -
|
|
|
|
dwDesiredAccess -
|
|
|
|
lpScHandle -
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPWSTR lpDatabaseNameW = NULL;
|
|
|
|
//
|
|
// This parameter got us to the server side and is uninteresting
|
|
// once we get here.
|
|
//
|
|
UNREFERENCED_PARAMETER(lpMachineName);
|
|
|
|
//
|
|
// Create a unicode version of lpDatabaseName
|
|
//
|
|
if (ARGUMENT_PRESENT(lpDatabaseName)) {
|
|
|
|
if(!ScConvertToUnicode(&lpDatabaseNameW, lpDatabaseName)) {
|
|
SC_LOG(ERROR,"ROpenSCManagerA:ScConvertToUnicode failed\n",0);
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
}
|
|
|
|
status = ROpenSCManagerW (
|
|
NULL,
|
|
lpDatabaseNameW,
|
|
dwDesiredAccess,
|
|
lpScHandle);
|
|
|
|
|
|
if (ARGUMENT_PRESENT(lpDatabaseName)) {
|
|
LocalFree(lpDatabaseNameW);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
|
|
DWORD
|
|
ROpenServiceA(
|
|
IN SC_RPC_HANDLE hSCManager,
|
|
IN LPSTR lpServiceName,
|
|
IN DWORD dwDesiredAccess,
|
|
OUT LPSC_RPC_HANDLE phService
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns a handle to the service. This handle is actually a pointer
|
|
to a data structure that contains a pointer to the service record.
|
|
|
|
Arguments:
|
|
|
|
hSCManager - This is a handle to this service controller. It is an
|
|
RPC context handle, and has allowed the request to get this far.
|
|
|
|
lpServiceName - This is a pointer to a string containing the name of
|
|
the service
|
|
|
|
dwDesiredAccess - This is an access mask that contains a description
|
|
of the access that is desired for this service.
|
|
|
|
phService - This is a pointer to the location where the handle to the
|
|
service is to be placed.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - The operation was successful.
|
|
|
|
ERROR_INVALID_HANDLE - The specified handle is invalid.
|
|
|
|
ERROR_SERVICE_DOES_NOT_EXIST - The specified service does not exist
|
|
in the database.
|
|
|
|
ERROR_NOT_ENOUGH_MEMORY - The memory allocation for the handle structure
|
|
failed.
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPWSTR lpServiceNameW;
|
|
|
|
//
|
|
// Create a unicode version of lpServiceName
|
|
//
|
|
if(!ScConvertToUnicode(&lpServiceNameW, lpServiceName)) {
|
|
SC_LOG(ERROR,"ROpenServiceA:ScConvertToUnicode failed\n",0);
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
status = ROpenServiceW (
|
|
hSCManager,
|
|
lpServiceNameW,
|
|
dwDesiredAccess,
|
|
phService);
|
|
|
|
LocalFree(lpServiceNameW);
|
|
|
|
return(status);
|
|
}
|
|
|
|
DWORD
|
|
RStartServiceA(
|
|
IN SC_RPC_HANDLE hService,
|
|
IN DWORD NumArgs,
|
|
IN LPSTRING_PTRSA CmdArgs
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function begins the execution of a service.
|
|
|
|
Arguments:
|
|
|
|
hService - A handle which is a pointer to a service handle structure.
|
|
|
|
dwNumServiceArgs - This indicates the number of argument vectors.
|
|
|
|
lpServiceArgVectors - This is a pointer to an array of string pointers.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - The operation was completely successful.
|
|
|
|
ERROR_ACCESS_DENIED - The specified handle was not opened with
|
|
SERVICE_START access.
|
|
|
|
ERROR_INVALID_HANDLE - The specified handle was invalid.
|
|
|
|
ERROR_SERVICE_WAS_STARTED - An instance of the service is already running.
|
|
|
|
ERROR_SERVICE_REQUEST_TIMEOUT - The service did not respond to the start
|
|
request in a timely fashion.
|
|
|
|
ERROR_SERVICE_NO_THREAD - A thread could not be created for the Win32
|
|
service.
|
|
|
|
ERROR_PATH_NOT_FOUND - The image file name could not be found in
|
|
the configuration database (registry), or the image file name
|
|
failed in a unicode/ansi conversion.
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = NO_ERROR;
|
|
LPWSTR *CmdArgsW = NULL;
|
|
DWORD bufferSize=0;
|
|
DWORD i;
|
|
LPSTR *cmdArgs;
|
|
|
|
if (NumArgs > 0) {
|
|
//
|
|
// If there are command args, create a unicode version of them.
|
|
//
|
|
|
|
//
|
|
// Allocate a buffer for the unicode command arg pointers.
|
|
//
|
|
bufferSize = NumArgs * sizeof(LPWSTR);
|
|
|
|
CmdArgsW = (LPWSTR *)LocalAlloc(LMEM_ZEROINIT, (UINT) bufferSize);
|
|
if (CmdArgsW == NULL) {
|
|
SC_LOG(ERROR,"RStartServicesA: LocalAlloc Failed\n",0);
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
__try {
|
|
|
|
//
|
|
// For each command Arg, allocate a string and convert the
|
|
// unicode version of the string into it.
|
|
//
|
|
cmdArgs = (LPSTR *)CmdArgs;
|
|
|
|
for (i=0; i<NumArgs; i++) {
|
|
if(!ScConvertToUnicode(&(CmdArgsW[i]), cmdArgs[i])) {
|
|
SC_LOG(ERROR,
|
|
"RStartServicesA: LocalAlloc (convert) Failed\n",0);
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
SC_LOG(ERROR,
|
|
"RStartServicesA: Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If any errors occured in the conversion process. Abort and
|
|
// return the error to the caller.
|
|
//
|
|
if (status != NO_ERROR) {
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
|
|
status = RStartServiceW(
|
|
hService,
|
|
NumArgs,
|
|
(LPSTRING_PTRSW)CmdArgsW);
|
|
|
|
CleanExit:
|
|
if (NumArgs > 0) {
|
|
//
|
|
// If there were unicode versions of the arguments created for
|
|
// this function, release the memory that was allocated.
|
|
//
|
|
for(i = 0; i < NumArgs; i++) {
|
|
if (CmdArgsW[i] != NULL) {
|
|
LocalFree(CmdArgsW[i]);
|
|
}
|
|
}
|
|
LocalFree(CmdArgsW);
|
|
}
|
|
|
|
return(status);
|
|
}
|
|
|
|
DWORD
|
|
REnumServicesStatusA (
|
|
IN SC_RPC_HANDLE hSCManager,
|
|
IN DWORD dwServiceType,
|
|
IN DWORD dwServiceState,
|
|
OUT PBYTE lpBuffer,
|
|
IN DWORD cbBufSize,
|
|
OUT LPDWORD pcbBytesNeeded,
|
|
OUT LPDWORD lpServicesReturned,
|
|
IN OUT LPDWORD lpResumeIndex OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function lists the services installed in the Service Controllers
|
|
database. The status of each service is returned with the name of
|
|
the service.
|
|
|
|
Arguments:
|
|
|
|
hSCManager - This is a handle to the service controller.
|
|
|
|
dwServiceType - Value to select the type of services to enumerate.
|
|
It must be one of the bitwise OR of the following values:
|
|
SERVICE_WIN32 - enumerate Win32 services only.
|
|
SERVICE_DRIVER - enumerate Driver services only.
|
|
|
|
dwServiceState - Value so select the services to enumerate based on the
|
|
running state. It must be one or the bitwise OR of the following
|
|
values:
|
|
SERVICE_ACTIVE - enumerate services that have started.
|
|
SERVICE_INACTIVE - enumerate services that are stopped.
|
|
|
|
lpBuffer - A pointer to a buffer to receive an array of enum status
|
|
(or service) entries.
|
|
|
|
cbBufSize - Size of the buffer in bytes pointed to by lpBuffer.
|
|
|
|
pcbBytesNeeded - A pointer to a location where the number of bytes
|
|
left (to be enumerated) is to be placed. This indicates to the
|
|
caller how large the buffer must be in order to complete the
|
|
enumeration with the next call.
|
|
|
|
lpServicesReturned - A pointer to a variable to receive the number of
|
|
of service entries returned.
|
|
|
|
lpResumeIndex - A pointer to a variable which on input specifies the
|
|
index of a service entry to begin enumeration. An index of 0
|
|
indicates to start at the beginning. On output, if this function
|
|
returns ERROR_MORE_DATA, the index returned is the next service
|
|
entry to resume the enumeration. The returned index is 0 if this
|
|
function returns a NO_ERROR.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - The operation was successful.
|
|
|
|
ERROR_MORE_DATA - Not all of the data in the active database could be
|
|
returned due to the size of the user's buffer. pcbBytesNeeded
|
|
contains the number of bytes required to get the remaining
|
|
entries.
|
|
|
|
ERROR_INVALID_PARAMETER - An illegal parameter value was passed in.
|
|
(such as dwServiceType).
|
|
|
|
ERROR_INVALID_HANDLE - The specified handle was invalid.
|
|
|
|
Note:
|
|
|
|
It is expected that the RPC Stub functions will find the following
|
|
parameter problems:
|
|
|
|
Bad pointers for lpBuffer, pcbReturned, pcbBytesNeeded,
|
|
lpBuffer, ReturnedServerName, and lpResumeIndex.
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPENUM_SERVICE_STATUS_WOW64 pEnumRec;
|
|
LPWSTR pServiceName;
|
|
LPWSTR pDisplayName;
|
|
DWORD i;
|
|
|
|
|
|
//
|
|
// Initialize entries returned because we convert the buffer on
|
|
// output based on the number of returned entries.
|
|
//
|
|
*lpServicesReturned = 0;
|
|
|
|
status = REnumServicesStatusW (
|
|
hSCManager,
|
|
dwServiceType,
|
|
dwServiceState,
|
|
lpBuffer,
|
|
cbBufSize,
|
|
pcbBytesNeeded,
|
|
lpServicesReturned,
|
|
lpResumeIndex);
|
|
|
|
if (*lpServicesReturned > 0)
|
|
{
|
|
//
|
|
// Convert the returned unicode structures to Ansi.
|
|
//
|
|
pEnumRec = (LPENUM_SERVICE_STATUS_WOW64) lpBuffer;
|
|
|
|
for (i = 0; i < *lpServicesReturned; i++)
|
|
{
|
|
//
|
|
// Note: in these conversions, the pointers to the names are
|
|
// stored as offsets at this point.
|
|
//
|
|
pServiceName = (LPWSTR) (lpBuffer + pEnumRec[i].dwServiceNameOffset);
|
|
pDisplayName = (LPWSTR) (lpBuffer + pEnumRec[i].dwDisplayNameOffset);
|
|
|
|
if (!ScConvertToAnsi((LPSTR) pServiceName, pServiceName))
|
|
{
|
|
SC_LOG(ERROR,"REnumServicesStatusA:ScConvertToAnsi failed\n",0);
|
|
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
*lpServicesReturned = 0;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Convert the Display Name.
|
|
//
|
|
if (!ScConvertToAnsi((LPSTR)pDisplayName, pDisplayName)) {
|
|
|
|
SC_LOG(ERROR,"REnumServicesStatusA:ScConvertToAnsi failed\n",0);
|
|
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
*lpServicesReturned = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(status);
|
|
}
|
|
|
|
|
|
DWORD
|
|
REnumServicesStatusExA (
|
|
IN SC_RPC_HANDLE hSCManager,
|
|
IN SC_ENUM_TYPE InfoLevel,
|
|
IN DWORD dwServiceType,
|
|
IN DWORD dwServiceState,
|
|
OUT PBYTE lpBuffer,
|
|
IN DWORD cbBufSize,
|
|
OUT LPDWORD pcbBytesNeeded,
|
|
OUT LPDWORD lpServicesReturned,
|
|
IN OUT LPDWORD lpResumeIndex OPTIONAL,
|
|
IN LPCSTR pszGroupNameAnsi
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is analogous to REnumServicesStatusA, with the data
|
|
being enumerated being dependent upon the InfoLevel parameter
|
|
|
|
Arguments:
|
|
|
|
InfoLevel - An enumerated type that determines what service attributes
|
|
are enumerated:
|
|
|
|
SC_ENUM_ALL_INFO - Enumerates all the service information from
|
|
REnumServicesStatusW plus the service's PID and flags
|
|
|
|
pszGroupName - Only enumerate services belonging to the given group.
|
|
If this parameter is the empty string, services not belonging to
|
|
a group are enumerated. If this parameter is NULL, no attention
|
|
is paid to group.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - The operation was successful.
|
|
|
|
ERROR_MORE_DATA - Not all of the data in the active database could be
|
|
returned due to the size of the user's buffer. pcbBytesNeeded
|
|
contains the number of bytes required to get the remaining
|
|
entries.
|
|
|
|
ERROR_INVALID_PARAMETER - An illegal parameter value was passed in.
|
|
(such as dwServiceType).
|
|
|
|
ERROR_INVALID_HANDLE - The specified handle was invalid.
|
|
|
|
ERROR_INVALID_LEVEL - The specified InfoLevel is invalid
|
|
|
|
Note:
|
|
|
|
It is expected that the RPC Stub functions will find the following
|
|
parameter problems:
|
|
|
|
Bad pointers for lpBuffer, pcbReturned, pcbBytesNeeded,
|
|
lpBuffer, ReturnedServerName, and lpResumeIndex.
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPENUM_SERVICE_STATUS_PROCESS_WOW64 pEnumRec;
|
|
LPWSTR pServiceName;
|
|
LPWSTR pDisplayName;
|
|
LPWSTR pszGroupName = NULL;
|
|
DWORD i;
|
|
|
|
|
|
//
|
|
// Initialize entries returned because we convert the buffer on
|
|
// output based on the number of returned entries.
|
|
//
|
|
*lpServicesReturned = 0;
|
|
|
|
if (ARGUMENT_PRESENT(pszGroupNameAnsi)) {
|
|
|
|
if (!ScConvertToUnicode(&pszGroupName, pszGroupNameAnsi)) {
|
|
SC_LOG(ERROR,"EnumServicesStatusExA: ScConvertToUnicode failed\n",0);
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
|
|
status = REnumServicesStatusExW (
|
|
hSCManager,
|
|
InfoLevel,
|
|
dwServiceType,
|
|
dwServiceState,
|
|
lpBuffer,
|
|
cbBufSize,
|
|
pcbBytesNeeded,
|
|
lpServicesReturned,
|
|
lpResumeIndex,
|
|
(LPCWSTR)pszGroupName);
|
|
|
|
if (*lpServicesReturned > 0)
|
|
{
|
|
//
|
|
// Convert the returned unicode structures to Ansi.
|
|
//
|
|
pEnumRec = (LPENUM_SERVICE_STATUS_PROCESS_WOW64) lpBuffer;
|
|
|
|
for (i = 0; i < *lpServicesReturned; i++) {
|
|
|
|
//
|
|
// Note: in these conversions, the pointers to the names are
|
|
// stored as offsets at this point.
|
|
//
|
|
pServiceName = (LPWSTR) (lpBuffer + pEnumRec[i].dwServiceNameOffset);
|
|
pDisplayName = (LPWSTR) (lpBuffer + pEnumRec[i].dwDisplayNameOffset);
|
|
|
|
if (!ScConvertToAnsi((LPSTR)pServiceName, pServiceName)) {
|
|
|
|
SC_LOG(ERROR,"REnumServicesStatusA:ScConvertToAnsi failed\n",0);
|
|
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
*lpServicesReturned = 0;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Convert the Display Name.
|
|
//
|
|
if (!ScConvertToAnsi((LPSTR)pDisplayName, pDisplayName)) {
|
|
|
|
SC_LOG(ERROR,"REnumServicesStatusA:ScConvertToAnsi failed\n",0);
|
|
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
*lpServicesReturned = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
LocalFree(pszGroupName);
|
|
|
|
return(status);
|
|
}
|
|
|
|
|
|
DWORD
|
|
RChangeServiceConfigA(
|
|
IN SC_RPC_HANDLE hService,
|
|
IN DWORD dwServiceType,
|
|
IN DWORD dwStartType,
|
|
IN DWORD dwErrorControl,
|
|
IN LPSTR lpBinaryPathName,
|
|
IN LPSTR lpLoadOrderGroup,
|
|
OUT LPDWORD lpdwTagId,
|
|
IN LPBYTE lpDependencies,
|
|
IN DWORD dwDependSize,
|
|
IN LPSTR lpServiceStartName,
|
|
IN LPBYTE EncryptedPassword,
|
|
IN DWORD PasswordSize,
|
|
IN LPSTR lpDisplayName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
lpDependencies - A buffer of size dwDependSize which already contains
|
|
Unicode strings.
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPWSTR lpDisplayNameW = NULL;
|
|
LPWSTR lpBinaryPathNameW = NULL;
|
|
LPWSTR lpLoadOrderGroupW = NULL;
|
|
LPWSTR lpServiceStartNameW = NULL;
|
|
|
|
//
|
|
// Create a unicode version of lpBinaryPathName
|
|
//
|
|
if (ARGUMENT_PRESENT(lpBinaryPathName)) {
|
|
|
|
if(!ScConvertToUnicode(&lpBinaryPathNameW, lpBinaryPathName)) {
|
|
SC_LOG(ERROR,"ChangeServiceConfigA:ScConvertToUnicode failed\n",0);
|
|
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Create a unicode version of lpLoadOrderGroup
|
|
//
|
|
if (ARGUMENT_PRESENT(lpLoadOrderGroup)) {
|
|
|
|
if(!ScConvertToUnicode(&lpLoadOrderGroupW, lpLoadOrderGroup)) {
|
|
SC_LOG(ERROR,"ChangeServiceConfigA:ScConvertToUnicode failed\n",0);
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Create a unicode version of lpServiceStartName
|
|
//
|
|
if (ARGUMENT_PRESENT(lpServiceStartName)) {
|
|
|
|
if(!ScConvertToUnicode(&lpServiceStartNameW, lpServiceStartName)) {
|
|
SC_LOG(ERROR,"ChangeServiceConfigA:ScConvertToUnicode failed\n",0);
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Create a unicode version of lpDisplayName
|
|
//
|
|
if (ARGUMENT_PRESENT(lpDisplayName)) {
|
|
|
|
if(!ScConvertToUnicode(&lpDisplayNameW, lpDisplayName)) {
|
|
SC_LOG(ERROR,"ChangeServiceConfigA:ScConvertToUnicode failed\n",0);
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the Unicode API Call
|
|
//
|
|
|
|
status = RChangeServiceConfigW(
|
|
(SC_RPC_HANDLE)hService,
|
|
dwServiceType,
|
|
dwStartType,
|
|
dwErrorControl,
|
|
lpBinaryPathNameW,
|
|
lpLoadOrderGroupW,
|
|
lpdwTagId,
|
|
lpDependencies,
|
|
dwDependSize,
|
|
lpServiceStartNameW,
|
|
EncryptedPassword,
|
|
PasswordSize,
|
|
lpDisplayNameW);
|
|
|
|
CleanExit:
|
|
|
|
LocalFree(lpBinaryPathNameW);
|
|
LocalFree(lpLoadOrderGroupW);
|
|
LocalFree(lpServiceStartNameW);
|
|
LocalFree(lpDisplayNameW);
|
|
|
|
return(status);
|
|
}
|
|
|
|
|
|
DWORD
|
|
RChangeServiceConfig2A(
|
|
IN SC_RPC_HANDLE hService,
|
|
IN SC_RPC_CONFIG_INFOA Info
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = NO_ERROR;
|
|
|
|
//
|
|
// Make a Unicode version of the arguments to pass to the Unicode function
|
|
//
|
|
union
|
|
{
|
|
SERVICE_DESCRIPTIONW sd;
|
|
SERVICE_FAILURE_ACTIONSW sfa;
|
|
} Buffer;
|
|
|
|
SC_RPC_CONFIG_INFOW InfoW = { Info.dwInfoLevel, &Buffer.sd };
|
|
|
|
switch (Info.dwInfoLevel)
|
|
{
|
|
case SERVICE_CONFIG_DESCRIPTION:
|
|
Buffer.sd.lpDescription = NULL;
|
|
|
|
if (Info.psd == NULL)
|
|
{
|
|
InfoW.psd = NULL;
|
|
break;
|
|
}
|
|
|
|
if (Info.psd->lpDescription != NULL)
|
|
{
|
|
if (!ScConvertToUnicode(&Buffer.sd.lpDescription,
|
|
Info.psd->lpDescription))
|
|
{
|
|
SC_LOG0(ERROR, "RChangeServiceConfig2A: ScConvertToUnicode failed\n");
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SERVICE_CONFIG_FAILURE_ACTIONS:
|
|
RtlCopyMemory(&Buffer.sfa, Info.psfa, sizeof(SERVICE_FAILURE_ACTIONS));
|
|
Buffer.sfa.lpRebootMsg = NULL;
|
|
Buffer.sfa.lpCommand = NULL;
|
|
|
|
if (Info.psfa == NULL)
|
|
{
|
|
InfoW.psfa = NULL;
|
|
break;
|
|
}
|
|
|
|
if (Info.psfa->lpRebootMsg != NULL)
|
|
{
|
|
if (!ScConvertToUnicode(&Buffer.sfa.lpRebootMsg,
|
|
Info.psfa->lpRebootMsg))
|
|
{
|
|
SC_LOG0(ERROR, "RChangeServiceConfig2A: ScConvertToUnicode failed\n");
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
|
|
if (Info.psfa->lpCommand != NULL)
|
|
{
|
|
if (!ScConvertToUnicode(&Buffer.sfa.lpCommand,
|
|
Info.psfa->lpCommand))
|
|
{
|
|
SC_LOG0(ERROR, "RChangeServiceConfig2A: ScConvertToUnicode failed\n");
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Call the Unicode function
|
|
//
|
|
status = RChangeServiceConfig2W(hService, InfoW);
|
|
|
|
CleanExit:
|
|
|
|
//
|
|
// Free the temporary Unicode strings
|
|
//
|
|
switch (Info.dwInfoLevel)
|
|
{
|
|
case SERVICE_CONFIG_DESCRIPTION:
|
|
LocalFree(Buffer.sd.lpDescription);
|
|
break;
|
|
|
|
case SERVICE_CONFIG_FAILURE_ACTIONS:
|
|
LocalFree(Buffer.sfa.lpRebootMsg);
|
|
LocalFree(Buffer.sfa.lpCommand);
|
|
break;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
RCreateServiceA(
|
|
IN SC_RPC_HANDLE hSCManager,
|
|
IN LPSTR lpServiceName,
|
|
IN LPSTR lpDisplayName,
|
|
IN DWORD dwDesiredAccess,
|
|
IN DWORD dwServiceType,
|
|
IN DWORD dwStartType,
|
|
IN DWORD dwErrorControl,
|
|
IN LPSTR lpBinaryPathName,
|
|
IN LPSTR lpLoadOrderGroup,
|
|
OUT LPDWORD lpdwTagId,
|
|
IN LPBYTE lpDependencies,
|
|
IN DWORD dwDependSize,
|
|
IN LPSTR lpServiceStartName,
|
|
IN LPBYTE EncryptedPassword,
|
|
IN DWORD PasswordSize,
|
|
IN OUT LPSC_RPC_HANDLE lpServiceHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
lpDependencies - A buffer of size dwDependSize which already contains
|
|
Unicode strings.
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPWSTR lpServiceNameW = NULL;
|
|
LPWSTR lpDisplayNameW = NULL;
|
|
LPWSTR lpBinaryPathNameW = NULL;
|
|
LPWSTR lpLoadOrderGroupW = NULL;
|
|
LPWSTR lpServiceStartNameW = NULL;
|
|
|
|
//
|
|
// Create a unicode version of lpServiceName
|
|
//
|
|
if (ARGUMENT_PRESENT(lpServiceName)) {
|
|
|
|
if(!ScConvertToUnicode(&lpServiceNameW, lpServiceName)) {
|
|
SC_LOG(ERROR,"RCreateServiceA:ScConvertToUnicode failed\n",0);
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
//
|
|
// Create a unicode version of lpDisplayName
|
|
//
|
|
if (ARGUMENT_PRESENT(lpDisplayName)) {
|
|
|
|
if(!ScConvertToUnicode(&lpDisplayNameW, lpDisplayName)) {
|
|
SC_LOG(ERROR,"RCreateServiceA:ScConvertToUnicode failed\n",0);
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
//
|
|
// Create a unicode version of lpBinaryPathName
|
|
//
|
|
if (ARGUMENT_PRESENT(lpBinaryPathName)) {
|
|
|
|
if(!ScConvertToUnicode(&lpBinaryPathNameW, lpBinaryPathName)) {
|
|
SC_LOG(ERROR,"RCreateServiceA:ScConvertToUnicode failed\n",0);
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Create a unicode version of lpLoadOrderGroup
|
|
//
|
|
if (ARGUMENT_PRESENT(lpLoadOrderGroup)) {
|
|
|
|
if(!ScConvertToUnicode(&lpLoadOrderGroupW, lpLoadOrderGroup)) {
|
|
SC_LOG(ERROR,"RCreateServiceA:ScConvertToUnicode failed\n",0);
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Create a unicode version of lpServiceStartName
|
|
//
|
|
if (ARGUMENT_PRESENT(lpServiceStartName)) {
|
|
|
|
if(!ScConvertToUnicode(&lpServiceStartNameW, lpServiceStartName)) {
|
|
SC_LOG(ERROR,"RCreateServiceA:ScConvertToUnicode failed\n",0);
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the Unicode API Call
|
|
//
|
|
|
|
status = RCreateServiceW (
|
|
(SC_RPC_HANDLE)hSCManager,
|
|
lpServiceNameW,
|
|
lpDisplayNameW,
|
|
dwDesiredAccess,
|
|
dwServiceType,
|
|
dwStartType,
|
|
dwErrorControl,
|
|
lpBinaryPathNameW,
|
|
lpLoadOrderGroupW,
|
|
lpdwTagId,
|
|
lpDependencies,
|
|
dwDependSize,
|
|
lpServiceStartNameW,
|
|
EncryptedPassword,
|
|
PasswordSize,
|
|
lpServiceHandle);
|
|
CleanExit:
|
|
|
|
LocalFree(lpServiceNameW);
|
|
LocalFree(lpDisplayNameW);
|
|
LocalFree(lpBinaryPathNameW);
|
|
LocalFree(lpLoadOrderGroupW);
|
|
LocalFree(lpServiceStartNameW);
|
|
|
|
return(status);
|
|
}
|
|
|
|
|
|
DWORD
|
|
REnumDependentServicesA(
|
|
IN SC_RPC_HANDLE hService,
|
|
IN DWORD dwServiceState,
|
|
OUT LPBYTE lpBuffer,
|
|
IN DWORD cbBufSize,
|
|
OUT LPDWORD pcbBytesNeeded,
|
|
OUT LPDWORD lpServicesReturned
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPENUM_SERVICE_STATUS_WOW64 pEnumRec;
|
|
LPWSTR pServiceName;
|
|
LPWSTR pDisplayName;
|
|
DWORD i;
|
|
|
|
//
|
|
// Initialize entries returned because we convert the buffer on
|
|
// output based on the number of returned entries.
|
|
//
|
|
*lpServicesReturned = 0;
|
|
|
|
status = REnumDependentServicesW(
|
|
hService,
|
|
dwServiceState,
|
|
lpBuffer,
|
|
cbBufSize,
|
|
pcbBytesNeeded,
|
|
lpServicesReturned);
|
|
|
|
if (*lpServicesReturned > 0) {
|
|
//
|
|
// Convert the returned unicode structures to Ansi.
|
|
//
|
|
pEnumRec = (LPENUM_SERVICE_STATUS_WOW64) lpBuffer;
|
|
|
|
for (i=0; i<*lpServicesReturned; i++) {
|
|
//
|
|
// Note: in these conversions, the pointers to the names are
|
|
// stored as offsets at this point.
|
|
//
|
|
pServiceName = (LPWSTR) (lpBuffer + (DWORD_PTR)(pEnumRec[i].dwServiceNameOffset));
|
|
pDisplayName = (LPWSTR) (lpBuffer + (DWORD_PTR)(pEnumRec[i].dwDisplayNameOffset));
|
|
|
|
if (!ScConvertToAnsi((LPSTR)pServiceName, pServiceName)) {
|
|
|
|
SC_LOG(ERROR,"REnumDependendServicesA:ScConvertToAnsi failed\n",0);
|
|
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
*lpServicesReturned = 0;
|
|
break;
|
|
}
|
|
//
|
|
// Convert the Display Name.
|
|
//
|
|
|
|
if (!ScConvertToAnsi((LPSTR)pDisplayName, pDisplayName)) {
|
|
|
|
SC_LOG(ERROR,"REnumServicesStatusA:ScConvertToAnsi failed\n",0);
|
|
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
*lpServicesReturned = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(status);
|
|
}
|
|
|
|
|
|
DWORD
|
|
RQueryServiceConfigA(
|
|
IN SC_RPC_HANDLE hService,
|
|
OUT LPQUERY_SERVICE_CONFIGA lpServiceConfig,
|
|
IN DWORD cbBufSize,
|
|
OUT LPDWORD pcbBytesNeeded
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
|
|
//
|
|
// Call the Unicode version of the API.
|
|
//
|
|
|
|
status = RQueryServiceConfigW(
|
|
(SC_RPC_HANDLE)hService,
|
|
(LPQUERY_SERVICE_CONFIGW)lpServiceConfig,
|
|
cbBufSize,
|
|
pcbBytesNeeded);
|
|
|
|
//
|
|
// If successful, convert the QUERY_SERVICE_CONFIG structure to
|
|
// ansi.
|
|
//
|
|
if (status == NO_ERROR) {
|
|
|
|
//
|
|
// Convert lpBinaryPathName to Ansi
|
|
//
|
|
if (lpServiceConfig->lpBinaryPathName != NULL) {
|
|
if(!ScConvertToAnsi(
|
|
lpServiceConfig->lpBinaryPathName,
|
|
((LPQUERY_SERVICE_CONFIGW)lpServiceConfig)->lpBinaryPathName)) {
|
|
|
|
SC_LOG(ERROR,"RQueryServiceConfigA:ScConvertToAnsi failed\n",0);
|
|
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
//
|
|
// Convert lpDisplayName to Ansi
|
|
//
|
|
if (lpServiceConfig->lpDisplayName != NULL) {
|
|
if(!ScConvertToAnsi(
|
|
lpServiceConfig->lpDisplayName,
|
|
((LPQUERY_SERVICE_CONFIGW)lpServiceConfig)->lpDisplayName)) {
|
|
|
|
SC_LOG(ERROR,"RQueryServiceConfigA:ScConvertToAnsi failed\n",0);
|
|
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
//
|
|
// Convert lpLoadOrderGroup to Ansi
|
|
//
|
|
if (lpServiceConfig->lpLoadOrderGroup != NULL) {
|
|
if(!ScConvertToAnsi(
|
|
lpServiceConfig->lpLoadOrderGroup,
|
|
((LPQUERY_SERVICE_CONFIGW)lpServiceConfig)->lpLoadOrderGroup)) {
|
|
|
|
SC_LOG(ERROR,"RQueryServiceConfigA:ScConvertToAnsi failed\n",0);
|
|
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
//
|
|
// Convert lpDependencies to Ansi
|
|
//
|
|
if (lpServiceConfig->lpDependencies != NULL) {
|
|
if(!ScConvertToAnsi(
|
|
lpServiceConfig->lpDependencies,
|
|
((LPQUERY_SERVICE_CONFIGW)lpServiceConfig)->lpDependencies)) {
|
|
|
|
SC_LOG(ERROR,"RQueryServiceConfigA:ScConvertToAnsi failed\n",0);
|
|
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
//
|
|
// Convert lpServiceStartName to Ansi
|
|
//
|
|
if (lpServiceConfig->lpServiceStartName != NULL) {
|
|
if(!ScConvertToAnsi(
|
|
lpServiceConfig->lpServiceStartName,
|
|
((LPQUERY_SERVICE_CONFIGW)lpServiceConfig)->lpServiceStartName)) {
|
|
|
|
SC_LOG(ERROR,"RQueryServiceConfigA:ScConvertToAnsi failed\n",0);
|
|
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(status);
|
|
}
|
|
|
|
DWORD
|
|
RQueryServiceConfig2A(
|
|
IN SC_RPC_HANDLE hService,
|
|
IN DWORD dwInfoLevel,
|
|
OUT LPBYTE lpBuffer,
|
|
IN DWORD cbBufSize,
|
|
OUT LPDWORD pcbBytesNeeded
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
DWORD StringOffset;
|
|
|
|
//
|
|
// Call the Unicode version of the API, using the same buffer.
|
|
// Then convert the strings in the buffer to Ansi.
|
|
//
|
|
status = RQueryServiceConfig2W(
|
|
hService,
|
|
dwInfoLevel,
|
|
lpBuffer,
|
|
cbBufSize,
|
|
pcbBytesNeeded
|
|
);
|
|
|
|
if (status == NO_ERROR)
|
|
{
|
|
switch (dwInfoLevel)
|
|
{
|
|
case SERVICE_CONFIG_DESCRIPTION:
|
|
{
|
|
StringOffset = ((LPSERVICE_DESCRIPTION_WOW64) lpBuffer)->dwDescriptionOffset;
|
|
|
|
if (StringOffset != 0)
|
|
{
|
|
if(!ScConvertToAnsi(
|
|
(LPSTR) (lpBuffer + StringOffset),
|
|
(LPWSTR) (lpBuffer + StringOffset)
|
|
))
|
|
{
|
|
SC_LOG0(ERROR,"RQueryServiceConfig2A:ScConvertToAnsi failed\n");
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SERVICE_CONFIG_FAILURE_ACTIONS:
|
|
{
|
|
StringOffset = ((LPSERVICE_FAILURE_ACTIONS_WOW64) lpBuffer)->dwRebootMsgOffset;
|
|
|
|
if (StringOffset != 0)
|
|
{
|
|
if(!ScConvertToAnsi(
|
|
(LPSTR) lpBuffer + StringOffset,
|
|
(LPWSTR) lpBuffer + StringOffset
|
|
))
|
|
{
|
|
SC_LOG0(ERROR,"RQueryServiceConfig2A:ScConvertToAnsi failed\n");
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
|
|
StringOffset = ((LPSERVICE_FAILURE_ACTIONS_WOW64) lpBuffer)->dwCommandOffset;
|
|
|
|
if (StringOffset != 0)
|
|
{
|
|
if(!ScConvertToAnsi(
|
|
(LPSTR) lpBuffer + StringOffset,
|
|
(LPWSTR) lpBuffer + StringOffset
|
|
))
|
|
{
|
|
SC_LOG0(ERROR,"RQueryServiceConfig2A:ScConvertToAnsi failed\n");
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
SC_ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
DWORD
|
|
RQueryServiceLockStatusA(
|
|
IN SC_RPC_HANDLE hSCManager,
|
|
OUT LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
|
|
IN DWORD cbBufSize,
|
|
OUT LPDWORD pcbBytesNeeded
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
|
|
//
|
|
// Call the Unicode version of the API
|
|
//
|
|
|
|
status = RQueryServiceLockStatusW(
|
|
(SC_RPC_HANDLE)hSCManager,
|
|
(LPQUERY_SERVICE_LOCK_STATUSW)lpLockStatus,
|
|
cbBufSize,
|
|
pcbBytesNeeded
|
|
);
|
|
|
|
//
|
|
// If successful, convert the QUERY_SERVICE_LOCK_STATUS structure to
|
|
// ansi.
|
|
//
|
|
if (status == NO_ERROR) {
|
|
|
|
//
|
|
// Convert lpLockOwner to Ansi
|
|
//
|
|
if (lpLockStatus->lpLockOwner != NULL) {
|
|
if(!ScConvertToAnsi(
|
|
lpLockStatus->lpLockOwner,
|
|
((LPQUERY_SERVICE_LOCK_STATUSW)lpLockStatus)->lpLockOwner)) {
|
|
|
|
SC_LOG(ERROR,"RQueryServiceLockStatusA:ScConvertToAnsi failed\n",0);
|
|
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
DWORD
|
|
RGetServiceDisplayNameA(
|
|
SC_RPC_HANDLE hSCManager,
|
|
LPSTR lpServiceName,
|
|
LPSTR lpDisplayName,
|
|
LPDWORD lpcchBuffer
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns the display name for a service that is identified
|
|
by its key name (ServiceName).
|
|
|
|
Arguments:
|
|
|
|
hSCManager - This is the handle to the Service Controller Manager that
|
|
is expected to return the display name.
|
|
|
|
lpServiceName - This is the ServiceName (which is actually a key
|
|
name) that identifies the service.
|
|
|
|
lpDisplayName - This is a pointer to a buffer that is to receive the
|
|
DisplayName string.
|
|
|
|
lpcchBuffer - This is a pointer to the size (in characters) of the
|
|
buffer that is to receive the DisplayName string. If the buffer
|
|
is not large enough to receive the entire string, then the required
|
|
buffer size is returned in this location. (NOTE: Ansi Characters,
|
|
including DBCS, are assumed to be 8 bits).
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPWSTR lpServiceNameW = NULL;
|
|
DWORD numChars = 0;
|
|
DWORD numBytes = 0;
|
|
LPSTR tempBuffer=NULL;
|
|
|
|
//
|
|
// Create a unicode version of lpServiceName
|
|
//
|
|
if (ARGUMENT_PRESENT(lpServiceName)) {
|
|
|
|
if(!ScConvertToUnicode(&lpServiceNameW, lpServiceName)) {
|
|
SC_LOG(ERROR,"RCreateServiceA:ScConvertToUnicode failed\n",0);
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Because of DBCS, we can't predict what the proper buffer size should
|
|
// be. So we allocate a temporary buffer that will hold as many
|
|
// unicode characters as the original buffer would hold single byte
|
|
// characters.
|
|
//
|
|
numChars = *lpcchBuffer;
|
|
|
|
numBytes = (*lpcchBuffer) * sizeof(WCHAR);
|
|
|
|
tempBuffer = (LPSTR) LocalAlloc(LMEM_FIXED, numBytes);
|
|
|
|
if (tempBuffer == NULL)
|
|
{
|
|
status = GetLastError();
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Make the Unicode API Call
|
|
//
|
|
|
|
status = RGetServiceDisplayNameW (
|
|
hSCManager,
|
|
lpServiceNameW,
|
|
(LPWSTR) tempBuffer,
|
|
&numChars);
|
|
|
|
if (status == NO_ERROR)
|
|
{
|
|
//
|
|
// Convert the returned Unicode string and string size back to
|
|
// ansi.
|
|
//
|
|
|
|
if (!ScConvertToAnsi(tempBuffer, (LPWSTR) tempBuffer)) {
|
|
SC_LOG0(ERROR, "RGetServiceDisplayNameA: ConvertToAnsi Failed\n");
|
|
}
|
|
|
|
numBytes = (DWORD) strlen(tempBuffer);
|
|
|
|
if ((numBytes+1) > *lpcchBuffer)
|
|
{
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
*lpcchBuffer = numBytes;
|
|
}
|
|
else
|
|
{
|
|
strcpy (lpDisplayName, tempBuffer);
|
|
}
|
|
}
|
|
else if (status == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
//
|
|
// Adjust the required buffer size for ansi.
|
|
//
|
|
*lpcchBuffer = numChars * sizeof(WCHAR);
|
|
}
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
|
|
LocalFree(tempBuffer);
|
|
LocalFree(lpServiceNameW);
|
|
|
|
return(status);
|
|
}
|
|
|
|
DWORD
|
|
RGetServiceKeyNameA(
|
|
SC_RPC_HANDLE hSCManager,
|
|
LPSTR lpDisplayName,
|
|
LPSTR lpServiceName,
|
|
LPDWORD lpcchBuffer
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPWSTR lpDisplayNameW = NULL;
|
|
DWORD numChars = 0;
|
|
DWORD numBytes = 0;
|
|
LPSTR tempBuffer=NULL;
|
|
|
|
//
|
|
// Create a unicode version of lpDisplayName
|
|
//
|
|
if (ARGUMENT_PRESENT(lpDisplayName))
|
|
{
|
|
if(!ScConvertToUnicode(&lpDisplayNameW, lpDisplayName))
|
|
{
|
|
SC_LOG(ERROR,"RGetServiceKeyNameA:ScConvertToUnicode failed\n",0);
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Because of DBCS, we can't predict what the proper buffer size should
|
|
// be. So we allocate a temporary buffer that will hold as many
|
|
// unicode characters as the original buffer would hold single byte
|
|
// characters.
|
|
//
|
|
numChars = *lpcchBuffer;
|
|
|
|
numBytes = (*lpcchBuffer) * sizeof(WCHAR);
|
|
|
|
tempBuffer = (LPSTR) LocalAlloc(LMEM_FIXED, numBytes);
|
|
|
|
if (tempBuffer == NULL)
|
|
{
|
|
status = GetLastError();
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Make the Unicode API Call
|
|
//
|
|
|
|
status = RGetServiceKeyNameW (
|
|
hSCManager,
|
|
lpDisplayNameW,
|
|
(LPWSTR)tempBuffer,
|
|
&numChars);
|
|
|
|
if (status == NO_ERROR)
|
|
{
|
|
//
|
|
// Convert the returned Unicode string and string size back to
|
|
// ansi.
|
|
//
|
|
|
|
if (!ScConvertToAnsi(tempBuffer, (LPWSTR)tempBuffer))
|
|
{
|
|
SC_LOG0(ERROR, "RGetServiceKeyNameA: ConvertToAnsi Failed\n");
|
|
}
|
|
|
|
numBytes = (DWORD) strlen(tempBuffer);
|
|
|
|
if ((numBytes+1) > *lpcchBuffer)
|
|
{
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
*lpcchBuffer = numBytes;
|
|
}
|
|
else
|
|
{
|
|
strcpy (lpServiceName, tempBuffer);
|
|
}
|
|
}
|
|
else if (status == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
//
|
|
// Adjust the required buffer size for ansi.
|
|
//
|
|
*lpcchBuffer = numChars * sizeof(WCHAR);
|
|
}
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
|
|
LocalFree(tempBuffer);
|
|
LocalFree(lpDisplayNameW);
|
|
|
|
return(status);
|
|
}
|