/*
 * Service Control Manager (SCM) interface definition
 */

#include <ms-dtyp.idl>

const unsigned int MAX_SERVICE_NAME_LENGTH = 256;
const unsigned short SC_MAX_DEPEND_SIZE = 4 * 1024;
const unsigned short SC_MAX_NAME_LENGTH = MAX_SERVICE_NAME_LENGTH + 1;
const unsigned short SC_MAX_PATH_LENGTH = 32 * 1024;
const unsigned short SC_MAX_PWD_SIZE = 514;
const unsigned short SC_MAX_COMPUTER_NAME_LENGTH = 1024;
const unsigned short SC_MAX_ACCOUNT_NAME_LENGTH = 2 * 1024;
const unsigned short SC_MAX_COMMENT_LENGTH = 128;
const unsigned short SC_MAX_ARGUMENT_LENGTH = 1024;
const unsigned short SC_MAX_ARGUMENTS = 1024;

typedef [handle] LPSTR SVCCTL_HANDLEA;
typedef [handle] LPWSTR SVCCTL_HANDLEW;
typedef [handle] ULONG_PTR RPC_SERVICE_STATUS_HANDLE;
typedef [context_handle] PVOID SC_RPC_HANDLE;
typedef SC_RPC_HANDLE* LPSC_RPC_HANDLE;
typedef [context_handle] PVOID SC_RPC_LOCK;
typedef SC_RPC_LOCK* LPSC_RPC_LOCK;
typedef [context_handle] PVOID SC_NOTIFY_RPC_HANDLE;
typedef SC_NOTIFY_RPC_HANDLE* LPSC_NOTIFY_RPC_HANDLE;
typedef [range(0, 1024 * 4)] DWORD BOUNDED_DWORD_4K;
typedef BOUNDED_DWORD_4K* LPBOUNDED_DWORD_4K;
typedef [range(0, 1024 * 8)] DWORD BOUNDED_DWORD_8K;
typedef BOUNDED_DWORD_8K* LPBOUNDED_DWORD_8K;
typedef [range(0, 1024 * 256)] DWORD BOUNDED_DWORD_256K;
typedef BOUNDED_DWORD_256K* LPBOUNDED_DWORD_256K;

cpp_quote("#if 0")

typedef struct _SERVICE_STATUS {
    DWORD dwServiceType;
    DWORD dwCurrentState;
    DWORD dwControlsAccepted;
    DWORD dwWin32ExitCode;
    DWORD dwServiceSpecificExitCode;
    DWORD dwCheckPoint;
    DWORD dwWaitHint;
} SERVICE_STATUS, *LPSERVICE_STATUS;

typedef struct _SERVICE_STATUS_PROCESS {
    DWORD dwServiceType;
    DWORD dwCurrentState;
    DWORD dwControlsAccepted;
    DWORD dwWin32ExitCode;
    DWORD dwServiceSpecificExitCode;
    DWORD dwCheckPoint;
    DWORD dwWaitHint;
    DWORD dwProcessId;
    DWORD dwServiceFlags;
} SERVICE_STATUS_PROCESS, *LPSERVICE_STATUS_PROCESS;

typedef struct _ENUM_SERVICE_STATUSA {
    [string] LPSTR lpServiceName;
    [string] LPSTR lpDisplayName;
    SERVICE_STATUS ServiceStatus;
} ENUM_SERVICE_STATUSA, *LPENUM_SERVICE_STATUSA;

typedef struct _ENUM_SERVICE_STATUSW {
    [string] LPWSTR lpServiceName;
    [string] LPWSTR lpDisplayName;
    SERVICE_STATUS ServiceStatus;
} ENUM_SERVICE_STATUSW, *LPENUM_SERVICE_STATUSW;

typedef struct _ENUM_SERVICE_STATUS_PROCESSA {
    [string] LPSTR lpServiceName;
    [string] LPSTR lpDisplayName;
    SERVICE_STATUS_PROCESS ServiceStatusProcess;
} ENUM_SERVICE_STATUS_PROCESSA, *LPENUM_SERVICE_STATUS_PROCESSA;

typedef struct _ENUM_SERVICE_STATUS_PROCESSW {
    [string] LPWSTR lpServiceName;
    [string] LPWSTR lpDisplayName;
    SERVICE_STATUS_PROCESS ServiceStatusProcess;
} ENUM_SERVICE_STATUS_PROCESSW, *LPENUM_SERVICE_STATUS_PROCESSW;

typedef struct _QUERY_SERVICE_CONFIGA {
    DWORD dwServiceType;
    DWORD dwStartType;
    DWORD dwErrorControl;
    [string] LPSTR lpBinaryPathName;
    [string] LPSTR lpLoadOrderGroup;
    DWORD dwTagId;
    [string] LPSTR lpDependencies;
    [string] LPSTR lpServiceStartName;
    LPSTR lpDisplayName;
} QUERY_SERVICE_CONFIGA, *LPQUERY_SERVICE_CONFIGA;

typedef struct _QUERY_SERVICE_CONFIGW {
    DWORD dwServiceType;
    DWORD dwStartType;
    DWORD dwErrorControl;
    [string] LPWSTR lpBinaryPathName;
    [string] LPWSTR lpLoadOrderGroup;
    DWORD dwTagId;
    [string] LPWSTR lpDependencies;
    [string] LPWSTR lpServiceStartName;
    LPWSTR lpDisplayName;
} QUERY_SERVICE_CONFIGW, *LPQUERY_SERVICE_CONFIGW;

typedef struct _QUERY_SERVICE_LOCK_STATUSA {
    DWORD fIsLocked;
    [string] LPSTR lpLockOwner;
    DWORD dwLockDuration;
} QUERY_SERVICE_LOCK_STATUSA, *LPQUERY_SERVICE_LOCK_STATUSA;

typedef struct _QUERY_SERVICE_LOCK_STATUSW {
    DWORD fIsLocked;
    [string] LPWSTR lpLockOwner;
    DWORD dwLockDuration;
} QUERY_SERVICE_LOCK_STATUSW, *LPQUERY_SERVICE_LOCK_STATUSW;

typedef [v1_enum] enum _SC_ACTION_TYPE {
    SC_ACTION_NONE = 0,
    SC_ACTION_RESTART = 1,
    SC_ACTION_REBOOT = 2,
    SC_ACTION_RUN_COMMAND = 3,
} SC_ACTION_TYPE;

typedef struct _SC_ACTION {
    SC_ACTION_TYPE Type;
    DWORD Delay;
} SC_ACTION, *LPSC_ACTION;

typedef [v1_enum] enum _SC_ENUM_TYPE {
    SC_ENUM_PROCESS_INFO = 0,
} SC_ENUM_TYPE;

typedef struct _SERVICE_DESCRIPTIONA {
    [string] LPSTR lpDescription;
} SERVICE_DESCRIPTIONA, *LPSERVICE_DESCRIPTIONA;

typedef struct _SERVICE_DESCRIPTIONW {
    [string] LPWSTR lpDescription;
} SERVICE_DESCRIPTIONW, *LPSERVICE_DESCRIPTIONW;

typedef struct _SERVICE_FAILURE_ACTIONSA {
    DWORD dwResetPeriod;
    [string] LPSTR lpRebootMsg;
    [string] LPSTR lpCommand;
    [range(0, 1024)] DWORD cActions;
    [size_is(cActions)] SC_ACTION* lpsaActions;
} SERVICE_FAILURE_ACTIONSA, *LPSERVICE_FAILURE_ACTIONSA;

typedef struct _SERVICE_FAILURE_ACTIONSW {
    DWORD dwResetPeriod;
    [string] LPWSTR lpRebootMsg;
    [string] LPWSTR lpCommand;
    [range(0, 1024)] DWORD cActions;
    [size_is(cActions)] SC_ACTION* lpsaActions;
} SERVICE_FAILURE_ACTIONSW, *LPSERVICE_FAILURE_ACTIONSW;

cpp_quote("#endif")

typedef struct _SERVICE_DELAYED_AUTO_START_INFO {
    BOOL fDelayedAutoStart;
} SERVICE_DELAYED_AUTO_START_INFO, *LPSERVICE_DELAYED_AUTO_START_INFO;

typedef struct _SERVICE_FAILURE_ACTIONS_FLAG {
    BOOL fFailureActionsOnNonCrashFailures;
} SERVICE_FAILURE_ACTIONS_FLAG, *LPSERVICE_FAILURE_ACTIONS_FLAG;

typedef struct _SERVICE_SID_INFO {
    DWORD dwServicesSidType;
} SERVICE_SID_INFO, *LPSERVICE_SID_INFO;

typedef struct _SERVICE_RPC_REQUIRED_PRIVILEGES_INFO {
    [range(0, 1024 * 4)] DWORD cbRequiredPrivileges;
    [size_is(cbRequiredPrivileges)] PBYTE pRequiredPrivileges;
} SERVICE_RPC_REQUIRED_PRIVILEGES_INFO, *LPSERVICE_RPC_REQUIRED_PRIVILEGES_INFO;

cpp_quote("#ifndef _SERVICE_PRESHUTDOWN_INFO_DEFINED_")
cpp_quote("#define _SERVICE_PRESHUTDOWN_INFO_DEFINED_")
typedef struct _SERVICE_PRESHUTDOWN_INFO {
    DWORD dwPreshutdownTimeout;
} SERVICE_PRESHUTDOWN_INFO, *LPSERVICE_PRESHUTDOWN_INFO;
cpp_quote("#endif")

typedef struct _SC_RPC_CONFIG_INFOA {
    DWORD dwInfoLevel;
    [switch_is(dwInfoLevel)] union {
        [case(1)] LPSERVICE_DESCRIPTIONA psd;
        [case(2)] LPSERVICE_FAILURE_ACTIONSA psfa;
        [case(3)] LPSERVICE_DELAYED_AUTO_START_INFO psda;
        [case(4)] LPSERVICE_FAILURE_ACTIONS_FLAG psfaf;
        [case(5)] LPSERVICE_SID_INFO pssid;
        [case(6)] LPSERVICE_RPC_REQUIRED_PRIVILEGES_INFO psrp;
        [case(7)] LPSERVICE_PRESHUTDOWN_INFO psps;
    } DUMMYUNIONNAME;
    [string] LPSTR lpDescription; //FIXME
} SC_RPC_CONFIG_INFOA, *LPSC_RPC_CONFIG_INFOA;

typedef struct _SC_RPC_CONFIG_INFOW {
    DWORD dwInfoLevel;
    [switch_is(dwInfoLevel)] union {
        [case(1)] LPSERVICE_DESCRIPTIONW psd;
        [case(2)] LPSERVICE_FAILURE_ACTIONSW psfa;
        [case(3)] LPSERVICE_DELAYED_AUTO_START_INFO psda;
        [case(4)] LPSERVICE_FAILURE_ACTIONS_FLAG psfaf;
        [case(5)] LPSERVICE_SID_INFO pssid;
        [case(6)] LPSERVICE_RPC_REQUIRED_PRIVILEGES_INFO psrp;
        [case(7)] LPSERVICE_PRESHUTDOWN_INFO psps;
    } DUMMYUNIONNAME;
} SC_RPC_CONFIG_INFOW, *LPSC_RPC_CONFIG_INFOW;

typedef struct _SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_1 {
    ULONGLONG ullThreadId;
    DWORD dwNotifyMask;
    UCHAR CallbackAddressArray[16];
    UCHAR CallbackParamAddressArray[16];
    SERVICE_STATUS_PROCESS ServiceStatus;
    DWORD dwNotificationStatus;
    DWORD dwSequence;
} SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_1, *PSERVICE_NOTIFY_STATUS_CHANGE_PARAMS_1;

typedef struct _SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2 {
    ULONGLONG ullThreadId;
    DWORD dwNotifyMask;
    UCHAR CallbackAddressArray[16];
    UCHAR CallbackParamAddressArray[16];
    SERVICE_STATUS_PROCESS ServiceStatus;
    DWORD dwNotificationStatus;
    DWORD dwSequence;
    DWORD dwNotificationTriggered;
    [string] PWSTR pszServiceNames;
} SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2, *PSERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2;

typedef struct _SC_RPC_NOTIFY_PARAMS {
    DWORD dwInfoLevel;
    [switch_is(dwInfoLevel)] union {
        [case(1)] PSERVICE_NOTIFY_STATUS_CHANGE_PARAMS_1 pStatusChangeParam1;
        [case(2)] PSERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2 pStatusChangeParam2;
    };
} SC_RPC_NOTIFY_PARAMS, *LPSC_RPC_NOTIFY_PARAMS;

typedef struct _SC_RPC_NOTIFY_PARAMS_LIST {
    BOUNDED_DWORD_4K cElements;
    [size_is(cElements)] SC_RPC_NOTIFY_PARAMS NotifyParamsArray[];
} SC_RPC_NOTIFY_PARAMS_LIST, *PSC_RPC_NOTIFY_PARAMS_LIST;

cpp_quote("#if 0")

#if 0
typedef
[switch_type(DWORD)] union _SC_RPC_SERVICE_CONTROL_IN_PARAMSA {
    [case(1)] PSERVICE_CONTROL_STATUS_REASON_IN_PARAMSA psrInParams;
} SC_RPC_SERVICE_CONTROL_IN_PARAMSA, *LPSC_RPC_SERVICE_CONTROL_IN_PARAMSA;

typedef
[switch_type(DWORD)] union _SC_RPC_SERVICE_CONTROL_IN_PARAMSW {
    [case(1)] PSERVICE_CONTROL_STATUS_REASON_IN_PARAMSW psrInParams;
} SC_RPC_SERVICE_CONTROL_IN_PARAMSW, *LPSC_RPC_SERVICE_CONTROL_IN_PARAMSW;

typedef
[switch_type(DWORD)] union _SC_RPC_SERVICE_CONTROL_OUT_PARAMSA {
    [case(1)] PSERVICE_CONTROL_STATUS_REASON_OUT_PARAMS psrOutParams;
} SC_RPC_SERVICE_CONTROL_OUT_PARAMSA, *LPSC_RPC_SERVICE_CONTROL_OUT_PARAMSA;

typedef
[switch_type(DWORD)] union _SC_RPC_SERVICE_CONTROL_OUT_PARAMSW {
    [case(1)] PSERVICE_CONTROL_STATUS_REASON_OUT_PARAMS psrOutParams;
} SC_RPC_SERVICE_CONTROL_OUT_PARAMSW, *LPSC_RPC_SERVICE_CONTROL_OUT_PARAMSW;
#endif

typedef [v1_enum] enum _SC_STATUS_TYPE {
    SC_STATUS_PROCESS_INFO = 0,
} SC_STATUS_TYPE;

typedef struct _SERVICE_CONTROL_STATUS_REASON_IN_PARAMSA {
    DWORD dwReason;
    [string] LPSTR pszComment;
} SERVICE_CONTROL_STATUS_REASON_IN_PARAMSA, *LPSERVICE_CONTROL_STATUS_REASON_IN_PARAMSA;

typedef struct _SERVICE_CONTROL_STATUS_REASON_IN_PARAMSW {
    DWORD dwReason;
    [string] LPWSTR pszComment;
} SERVICE_CONTROL_STATUS_REASON_IN_PARAMSW, *LPSERVICE_CONTROL_STATUS_REASON_IN_PARAMSW;

typedef struct _SERVICE_CONTROL_STATUS_REASON_OUT_PARAMS {
    SERVICE_STATUS_PROCESS ServiceStatus;
} SERVICE_CONTROL_STATUS_REASON_OUT_PARAMS, *LPSERVICE_CONTROL_STATUS_REASON_OUT_PARAMS;

typedef SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2 SERVICE_NOTIFY_STATUS_CHANGE_PARAMS, *LPSERVICE_NOTIFY_STATUS_CHANGE_PARAMS;

cpp_quote("#endif")

typedef struct _STRING_PTRSA {
    [string] LPSTR StringPtr;
} STRING_PTRSA, *PSTRING_PTRSA, *LPSTRING_PTRSA;

typedef struct _STRING_PTRSW {
    [string] LPWSTR StringPtr;
} STRING_PTRSW, *PSTRING_PTRSW, *LPSTRING_PTRSW;

[
  uuid(367abb81-9844-35f1-ad32-98f038001003),
  version(2.0),
  pointer_default(unique),
  endpoint("ncacn_np:[\\pipe\\ntsvcs]")
]
interface svcctl
{
    /* Function 0 */
    DWORD RCloseServiceHandle(
        [in, out] LPSC_RPC_HANDLE hSCObject);

    /* Function 1 */
    DWORD RControlService(
        [in] SC_RPC_HANDLE hService,
        [in] DWORD dwControl,
        [out] LPSERVICE_STATUS lpServiceStatus);

    /* Function 2 */
    DWORD RDeleteService(
        [in] SC_RPC_HANDLE hService);

    /* Function 3 */
    DWORD RLockServiceDatabase(
        [in] SC_RPC_HANDLE hSCManager,
        [out] LPSC_RPC_LOCK lpLock);

    /* Function 4 */
    DWORD RQueryServiceObjectSecurity(
        [in] SC_RPC_HANDLE hService,
        [in] SECURITY_INFORMATION dwSecurityInformation,
        [out, size_is(cbBufSize)] LPBYTE lpSecurityDescriptor,
        [in, range(0, 1024 * 256)] DWORD cbBufSize,
        [out] LPBOUNDED_DWORD_256K pcbBytesNeeded);

    /* Function 5 */
    DWORD RSetServiceObjectSecurity(
        [in] SC_RPC_HANDLE hService,
        [in] DWORD dwSecurityInformation,
        [in, size_is(dwSecuityDescriptorSize)] LPBYTE lpSecurityDescriptor,
        [in] DWORD dwSecuityDescriptorSize);

    /* Function 6 */
    DWORD RQueryServiceStatus(
        [in] SC_RPC_HANDLE hService,
        [out] LPSERVICE_STATUS lpServiceStatus);

    /* Function 7 */
    DWORD RSetServiceStatus(
      [in] RPC_SERVICE_STATUS_HANDLE hServiceStatus,
      [in] LPSERVICE_STATUS lpServiceStatus);

    /* Function 8 */
    DWORD RUnlockServiceDatabase(
        [in, out] LPSC_RPC_LOCK Lock);

    /* Function 9 */
    DWORD RNotifyBootConfigStatus(
        [in, string, unique] SVCCTL_HANDLEW lpMachineName,
        [in] DWORD BootAcceptable);

    /* Function 10 */
    DWORD RI_ScSetServiceBitsW(
        [in] RPC_SERVICE_STATUS_HANDLE hServiceStatus,
        [in] DWORD dwServiceBits,
        [in] BOOL bSetBitsOn,
        [in] BOOL bUpdateImmediately,
        [in, string, unique] LPWSTR lpString);

    /* Function 11 */
    DWORD RChangeServiceConfigW(
        [in] SC_RPC_HANDLE hService,
        [in] DWORD dwServiceType,
        [in] DWORD dwStartType,
        [in] DWORD dwErrorControl,
        [in, string, unique] LPWSTR lpBinaryPathName,
        [in, string, unique] LPWSTR lpLoadOrderGroup,
        [in, out, unique] LPDWORD lpdwTagId,
        [in, unique, size_is(dwDependSize)] LPBYTE lpDependencies,
        [in, range(0, SC_MAX_DEPEND_SIZE)] DWORD dwDependSize,
        [in, string, unique] LPWSTR lpServiceStartName,
        [in, unique, size_is(dwPwSize)] LPBYTE lpPassword,
        [in, range(0, SC_MAX_PWD_SIZE)] DWORD dwPwSize,
        [in, string, unique] LPWSTR lpDisplayName);

    /* Function 12 */
    DWORD RCreateServiceW(
        [in] SC_RPC_HANDLE hSCManager,
        [in, string] LPCWSTR lpServiceName,
        [in, string, unique] LPCWSTR lpDisplayName,
        [in] DWORD dwDesiredAccess,
        [in] DWORD dwServiceType,
        [in] DWORD dwStartType,
        [in] DWORD dwErrorControl,
        [in, string] LPCWSTR lpBinaryPathName,
        [in, string, unique] LPCWSTR lpLoadOrderGroup,
        [in, out, unique] LPDWORD lpdwTagId,
        [in, unique, size_is(dwDependSize)] LPBYTE lpDependencies,
        [in, range(0, SC_MAX_DEPEND_SIZE)] DWORD dwDependSize,
        [in, string, unique] LPCWSTR lpServiceStartName,
        [in, unique, size_is(dwPwSize)] LPBYTE lpPassword,
        [in, range(0, SC_MAX_PWD_SIZE)] DWORD dwPwSize,
        [out] LPSC_RPC_HANDLE lpServiceHandle);

    /* Function 13 */
    DWORD REnumDependentServicesW(
        [in] SC_RPC_HANDLE hService,
        [in] DWORD dwServiceState,
        [out, size_is(cbBufSize)] LPBYTE lpServices,
        [in, range(0, 1024*256)] DWORD cbBufSize,
        [out] LPBOUNDED_DWORD_256K pcbBytesNeeded,
        [out] LPBOUNDED_DWORD_256K lpServicesReturned);

    /* Function 14 */
    DWORD REnumServicesStatusW(
        [in] SC_RPC_HANDLE hSCManager,
        [in] DWORD dwServiceType,
        [in] DWORD dwServiceState,
        [out, size_is(dwBufSize)] LPBYTE lpBuffer,
        [in, range(0, 1024*256)] DWORD dwBufSize,
        [out] LPBOUNDED_DWORD_256K pcbBytesNeeded,
        [out] LPBOUNDED_DWORD_256K lpServicesReturned,
        [in, out, unique] LPBOUNDED_DWORD_256K lpResumeHandle);

    /* Function 15 */
    DWORD ROpenSCManagerW(
        [in, string, unique] SVCCTL_HANDLEW lpMachineName,
        [in, string, unique] LPWSTR lpDatabaseName,
        [in] DWORD dwDesiredAccess,
        [out] LPSC_RPC_HANDLE lpScHandle);

    /* Function 16 */
    DWORD ROpenServiceW(
        [in] SC_RPC_HANDLE hSCManager,
        [in, string] LPWSTR lpServiceName,
        [in] DWORD dwDesiredAccess,
        [out] LPSC_RPC_HANDLE lpServiceHandle);

    /* Function 17 */
    DWORD RQueryServiceConfigW(
        [in] SC_RPC_HANDLE hService,
        [out, size_is(cbBufSize)] LPBYTE lpServiceConfig,
        /* FIXME: should be [out] LPQUERY_SERVICE_CONFIGW lpServiceConfig, */
        [in, range(0, 1024*8)] DWORD cbBufSize,
        [out] LPBOUNDED_DWORD_8K pcbBytesNeeded);

    /* Function 18 */
    DWORD RQueryServiceLockStatusW(
        [in] SC_RPC_HANDLE hSCManager,
        [out, size_is(cbBufSize)] LPBYTE lpLockStatus,
        /* FIXME: should be [out] LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus, */
        [in, range(0, 1024*4)] DWORD cbBufSize,
        [out] LPBOUNDED_DWORD_4K pcbBytesNeeded);

    /* Function 19 */
    DWORD RStartServiceW(
        [in] SC_RPC_HANDLE hService,
        [in, range(0, SC_MAX_ARGUMENTS)] DWORD argc,
        [in, unique, size_is(argc)] LPSTRING_PTRSW argv);

    /* Function 20 */
    DWORD RGetServiceDisplayNameW(
        [in] SC_RPC_HANDLE hSCManager,
        [in, string] LPCWSTR lpServiceName,
        [out, string, size_is(*lpcchBuffer + 1)] LPWSTR lpDisplayName,
        [in, out] DWORD* lpcchBuffer);

    /* Function 21 */
    DWORD RGetServiceKeyNameW(
        [in] SC_RPC_HANDLE hSCManager,
        [in, string] LPCWSTR lpDisplayName,
        [out, string, size_is(*lpcchBuffer + 1)] LPWSTR lpServiceName,
        [in, out] DWORD* lpcchBuffer);

    /* Function 22 */
    DWORD RI_ScSetServiceBitsA(
        [in] RPC_SERVICE_STATUS_HANDLE hServiceStatus,
        [in] DWORD dwServiceBits,
        [in] BOOL bSetBitsOn,
        [in] BOOL bUpdateImmediately,
        [in, string, unique] LPSTR lpString);

    /* Function 23 */
    DWORD RChangeServiceConfigA(
        [in] SC_RPC_HANDLE hService,
        [in] DWORD dwServiceType,
        [in] DWORD dwStartType,
        [in] DWORD dwErrorControl,
        [in, string, unique] LPSTR lpBinaryPathName,
        [in, string, unique] LPSTR lpLoadOrderGroup,
        [in, out, unique] LPDWORD lpdwTagId,
        [in, unique, size_is(dwDependSize)] LPBYTE lpDependencies,
        [in, range(0, SC_MAX_DEPEND_SIZE)] DWORD dwDependSize,
        [in, string, unique] LPSTR lpServiceStartName,
        [in, unique, size_is(dwPwSize)] LPBYTE lpPassword,
        [in, range(0, SC_MAX_PWD_SIZE)] DWORD dwPwSize,
        [in, string, unique] LPSTR lpDisplayName);

    /* Function 24 */
    DWORD RCreateServiceA(
        [in] SC_RPC_HANDLE hSCManager,
        [in, string] LPSTR lpServiceName,
        [in, string, unique] LPSTR lpDisplayName,
        [in] DWORD dwDesiredAccess,
        [in] DWORD dwServiceType,
        [in] DWORD dwStartType,
        [in] DWORD dwErrorControl,
        [in, string] LPSTR lpBinaryPathName,
        [in, string, unique] LPSTR lpLoadOrderGroup,
        [in, out, unique] LPDWORD lpdwTagId,
        [in, unique, size_is(dwDependSize)] LPBYTE lpDependencies,
        [in, range(0, SC_MAX_DEPEND_SIZE)] DWORD dwDependSize,
        [in, string, unique] LPSTR lpServiceStartName,
        [in, unique, size_is(dwPwSize)] LPBYTE lpPassword,
        [in, range(0, SC_MAX_PWD_SIZE)] DWORD dwPwSize,
        [out] LPSC_RPC_HANDLE lpServiceHandle);

    /* Function 25 */
    DWORD REnumDependentServicesA(
        [in] SC_RPC_HANDLE hService,
        [in] DWORD dwServiceState,
        [out, size_is(cbBufSize)] LPBYTE lpServices,
        [in, range(0, 1024*256)] DWORD cbBufSize,
        [out] LPBOUNDED_DWORD_256K pcbBytesNeeded,
        [out] LPBOUNDED_DWORD_256K lpServicesReturned);

    /* Function 26 */
    DWORD REnumServicesStatusA(
        [in] SC_RPC_HANDLE hSCManager,
        [in] DWORD dwServiceType,
        [in] DWORD dwServiceState,
        [out, size_is(dwBufSize)] LPBYTE lpBuffer,
        [in, range(0, 1024*256)] DWORD dwBufSize,
        [out] LPBOUNDED_DWORD_256K pcbBytesNeeded,
        [out] LPBOUNDED_DWORD_256K lpServicesReturned,
        [in, out, unique] LPBOUNDED_DWORD_256K lpResumeHandle);

    /* Function 27 */
    DWORD ROpenSCManagerA(
        [in, string, unique] SVCCTL_HANDLEA lpMachineName,
        [in, string, unique] LPSTR lpDatabaseName,
        [in] DWORD dwDesiredAccess,
        [out] LPSC_RPC_HANDLE lpScHandle);

    /* Function 28 */
    DWORD ROpenServiceA(
        [in] SC_RPC_HANDLE hSCManager,
        [in, string] LPSTR lpServiceName,
        [in] DWORD dwDesiredAccess,
        [out] LPSC_RPC_HANDLE lpServiceHandle);

    /* Function 29 */
    DWORD RQueryServiceConfigA(
        [in] SC_RPC_HANDLE hService,
        [out, size_is(cbBufSize)] LPBYTE lpServiceConfig,
        /* FIXME: should be [out] LPQUERY_SERVICE_CONFIGA lpServiceConfig, */
        [in, range(0, 1024*8)] DWORD cbBufSize,
        [out] LPBOUNDED_DWORD_8K pcbBytesNeeded);

    /* Function 30 */
    DWORD RQueryServiceLockStatusA(
        [in] SC_RPC_HANDLE hSCManager,
        [out, size_is(cbBufSize)] LPBYTE lpLockStatus,
        /* FIXME: should be [out] LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus, */
        [in, range(0, 1024*4)] DWORD cbBufSize,
        [out] LPBOUNDED_DWORD_4K pcbBytesNeeded);

    /* Function 31 */
    DWORD RStartServiceA(
        [in] SC_RPC_HANDLE hService,
        [in, range(0, SC_MAX_ARGUMENTS)] DWORD argc,
        [in, unique, size_is(argc)] LPSTRING_PTRSA argv);

    /* Function 32 */
    DWORD RGetServiceDisplayNameA(
        [in] SC_RPC_HANDLE hSCManager,
        [in, string] LPCSTR lpServiceName,
        [out, string, size_is(*lpcchBuffer)] LPSTR lpDisplayName,
        [in, out] LPBOUNDED_DWORD_4K lpcchBuffer);

    /* Function 33 */
    DWORD RGetServiceKeyNameA(
        [in] SC_RPC_HANDLE hSCManager,
        [in, string] LPCSTR lpDisplayName,
        [out, string, size_is(*lpcchBuffer)] LPSTR lpKeyName,
        [in, out] LPBOUNDED_DWORD_4K lpcchBuffer);

    /* Function 34 */
    DWORD RI_ScGetCurrentGroupStateW(
        [in] SC_RPC_HANDLE hSCManager,
        [in, string, unique] LPWSTR lpLoadOrderGroup,
        [out] LPDWORD lpState);

    /* Function 35 */
    DWORD REnumServiceGroupW(
        [in] SC_RPC_HANDLE hSCManager,
        [in] DWORD dwServiceType,
        [in] DWORD dwServiceState,
        [out, size_is(cbBufSize)] LPBYTE lpBuffer,
        [in, range(0, 1024*256)] DWORD cbBufSize,
        [out] LPBOUNDED_DWORD_256K pcbBytesNeeded,
        [out] LPBOUNDED_DWORD_256K lpServicesReturned,
        [in, out, unique] LPBOUNDED_DWORD_256K lpResumeIndex,
        [in, string, unique] LPCWSTR pszGroupName);

    /* Function 36 */
    DWORD RChangeServiceConfig2A(
        [in] SC_RPC_HANDLE hService,
        [in] SC_RPC_CONFIG_INFOA Info);

    /* Function 37 */
    DWORD RChangeServiceConfig2W(
        [in] SC_RPC_HANDLE hService,
        [in] SC_RPC_CONFIG_INFOW Info);

    /* Function 38 */
    DWORD RQueryServiceConfig2A(
        [in] SC_RPC_HANDLE hService,
        [in] DWORD dwInfoLevel,
        [out, size_is(cbBufSize)] LPBYTE lpBuffer,
        [in, range(0, 1024*8)] DWORD cbBufSize,
        [out] LPBOUNDED_DWORD_8K pcbBytesNeeded);

    /* Function 39 */
    DWORD RQueryServiceConfig2W(
        [in] SC_RPC_HANDLE hService,
        [in] DWORD dwInfoLevel,
        [out, size_is(cbBufSize)] LPBYTE lpBuffer,
        [in, range(0, 1024*8)] DWORD cbBufSize,
        [out] LPBOUNDED_DWORD_8K pcbBytesNeeded);

    /* Function 40 */
    DWORD RQueryServiceStatusEx(
        [in] SC_RPC_HANDLE hService,
        [in] SC_STATUS_TYPE InfoLevel,
        [out, size_is(cbBufSize)] LPBYTE lpBuffer,
        [in, range(0, 1024*8)] DWORD cbBufSize,
        [out] LPBOUNDED_DWORD_8K pcbBytesNeeded);

    /* Function 41 */
    DWORD REnumServicesStatusExA(
        [in] SC_RPC_HANDLE hSCManager,
        [in] SC_ENUM_TYPE InfoLevel,
        [in] DWORD dwServiceType,
        [in] DWORD dwServiceState,
        [out, size_is(cbBufSize)] LPBYTE lpBuffer,
        [in, range(0, 1024 * 256)] DWORD cbBufSize,
        [out] LPBOUNDED_DWORD_256K pcbBytesNeeded,
        [out] LPBOUNDED_DWORD_256K lpServicesReturned,
        [in, out, unique] LPBOUNDED_DWORD_256K lpResumeIndex,
        [in, string, unique] LPCSTR pszGroupName);

    /* Function 42 */
    DWORD REnumServicesStatusExW(
        [in] SC_RPC_HANDLE hSCManager,
        [in] SC_ENUM_TYPE InfoLevel,
        [in] DWORD dwServiceType,
        [in] DWORD dwServiceState,
        [out, size_is(cbBufSize)] LPBYTE lpBuffer,
        [in, range(0, 1024 * 256)] DWORD cbBufSize,
        [out] LPBOUNDED_DWORD_256K pcbBytesNeeded,
        [out] LPBOUNDED_DWORD_256K lpServicesReturned,
        [in, out, unique] LPBOUNDED_DWORD_256K lpResumeIndex,
        [in, string, unique] LPCWSTR pszGroupName);

    /* Function 43 */
    DWORD RSendTSMessage(
        [in] handle_t BindingHandle); /* FIXME */

    /* Function 44 */
    DWORD RCreateServiceWOW64A(
        [in] handle_t BindingHandle,
        [in, string] LPSTR lpServiceName,
        [in, string, unique] LPSTR lpDisplayName,
        [in] DWORD dwDesiredAccess,
        [in] DWORD dwServiceType,
        [in] DWORD dwStartType,
        [in] DWORD dwErrorControl,
        [in, string] LPSTR lpBinaryPathName,
        [in, string, unique] LPSTR lpLoadOrderGroup,
        [in, out, unique] LPDWORD lpdwTagId,
        [in, unique, size_is(dwDependSize)] LPBYTE lpDependencies,
        [in, range(0, SC_MAX_DEPEND_SIZE)] DWORD dwDependSize,
        [in, string, unique] LPSTR lpServiceStartName,
        [in, unique, size_is(dwPwSize)] LPBYTE lpPassword,
        [in, range(0, SC_MAX_PWD_SIZE)] DWORD dwPwSize,
        [out] LPSC_RPC_HANDLE lpServiceHandle);

    /* Function 45 */
    DWORD RCreateServiceWOW64W(
        [in] handle_t BindingHandle,
        [in, string] LPWSTR lpServiceName,
        [in, string, unique] LPWSTR lpDisplayName,
        [in] DWORD dwDesiredAccess,
        [in] DWORD dwServiceType,
        [in] DWORD dwStartType,
        [in] DWORD dwErrorControl,
        [in, string] LPWSTR lpBinaryPathName,
        [in, string, unique] LPWSTR lpLoadOrderGroup,
        [in, out, unique] LPDWORD lpdwTagId,
        [in, unique, size_is(dwDependSize)] LPBYTE lpDependencies,
        [in, range(0, SC_MAX_DEPEND_SIZE)] DWORD dwDependSize,
        [in, string, unique] LPWSTR lpServiceStartName,
        [in, unique, size_is(dwPwSize)] LPBYTE lpPassword,
        [in, range(0, SC_MAX_PWD_SIZE)] DWORD dwPwSize,
        [out] LPSC_RPC_HANDLE lpServiceHandle);

    /* Function 46 */
    DWORD RQueryServiceTagInfo(
        [in] handle_t BindingHandle); /* FIXME */

    /* Function 47 */
    DWORD RNotifyServiceStatusChange(
        [in] SC_RPC_HANDLE hService,
        [in] SC_RPC_NOTIFY_PARAMS NotifyParams,
        [in] GUID* pClientProcessGuid,
        [out] GUID* pSCMProcessGuid,
        [out] PBOOL pfCreateRemoteQueue,
        [out] LPSC_NOTIFY_RPC_HANDLE phNotify);

    /* Function 48 */
    DWORD RGetNotifyResults(
        [in] SC_NOTIFY_RPC_HANDLE hNotify,
        [out] PSC_RPC_NOTIFY_PARAMS_LIST *ppNotifyParams);

    /* Function 49 */
    DWORD RCloseNotifyHandle(
        [in, out] LPSC_NOTIFY_RPC_HANDLE phNotify,
        [out] PBOOL pfApcFired);

    /* Function 50 */
    DWORD RControlServiceExA(
        [in] SC_RPC_HANDLE hService,
        [in] DWORD dwControl,
        [in] DWORD dwInfoLevel/*,
        [in, switch_is(dwInfoLevel)] PSC_RPC_SERVICE_CONTROL_IN_PARAMSA pControlInParams,
        [out, switch_is(dwInfoLevel)] PSC_RPC_SERVICE_CONTROL_IN_PARAMSA pControlOutParams*/);

    /* Function 51 */
    DWORD RControlServiceExW(
        [in] SC_RPC_HANDLE hService,
        [in] DWORD dwControl,
        [in] DWORD dwInfoLevel/*,
        [in, switch_is(dwInfoLevel)] PSC_RPC_SERVICE_CONTROL_IN_PARAMSW pControlInParams,
        [out, switch_is(dwInfoLevel)] PSC_RPC_SERVICE_CONTROL_IN_PARAMSW pControlOutParams*/);

    /* Function 52 */
    DWORD RSendPnPMessage(
        [in] handle_t BindingHandle); /* FIXME */

    /* Function 53 */
    DWORD RValidatePnPService(
        [in] handle_t BindingHandle); /* FIXME */

    /* Function 54 */
    DWORD ROpenServiceStatusHandle(
        [in] handle_t BindingHandle); /* FIXME */

    /* Function 55 */
    DWORD RFunction55(
        [in] handle_t BindingHandle); /* FIXME */
}
