xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/svcctl_svc.c (revision 10001:d540bbbe2461)
17961SNatalie.Li@Sun.COM /*
27961SNatalie.Li@Sun.COM  * CDDL HEADER START
37961SNatalie.Li@Sun.COM  *
47961SNatalie.Li@Sun.COM  * The contents of this file are subject to the terms of the
57961SNatalie.Li@Sun.COM  * Common Development and Distribution License (the "License").
67961SNatalie.Li@Sun.COM  * You may not use this file except in compliance with the License.
77961SNatalie.Li@Sun.COM  *
87961SNatalie.Li@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97961SNatalie.Li@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107961SNatalie.Li@Sun.COM  * See the License for the specific language governing permissions
117961SNatalie.Li@Sun.COM  * and limitations under the License.
127961SNatalie.Li@Sun.COM  *
137961SNatalie.Li@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147961SNatalie.Li@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157961SNatalie.Li@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167961SNatalie.Li@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177961SNatalie.Li@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187961SNatalie.Li@Sun.COM  *
197961SNatalie.Li@Sun.COM  * CDDL HEADER END
207961SNatalie.Li@Sun.COM  */
217961SNatalie.Li@Sun.COM /*
22*10001SJoyce.McIntosh@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237961SNatalie.Li@Sun.COM  * Use is subject to license terms.
247961SNatalie.Li@Sun.COM  */
257961SNatalie.Li@Sun.COM 
267961SNatalie.Li@Sun.COM /*
277961SNatalie.Li@Sun.COM  * Service Control Services (SVCCTL) RPC interface definition.
287961SNatalie.Li@Sun.COM  * This interface provides remote access to list SMF services
297961SNatalie.Li@Sun.COM  * from a Windows client.
307961SNatalie.Li@Sun.COM  *
317961SNatalie.Li@Sun.COM  * SVCCTL access is restricted to administrators: members of the
327961SNatalie.Li@Sun.COM  * Domain Admins or Administrators groups.
337961SNatalie.Li@Sun.COM  */
348334SJose.Borrego@Sun.COM 
357961SNatalie.Li@Sun.COM #include <stdio.h>
367961SNatalie.Li@Sun.COM #include <strings.h>
377961SNatalie.Li@Sun.COM #include <smbsrv/ntstatus.h>
387961SNatalie.Li@Sun.COM #include <smbsrv/nmpipes.h>
39*10001SJoyce.McIntosh@Sun.COM #include <smbsrv/ntifs.h>
407961SNatalie.Li@Sun.COM #include "svcctl_scm.h"
417961SNatalie.Li@Sun.COM 
42*10001SJoyce.McIntosh@Sun.COM #define	SVCCTL_SECURITY_BUFSIZE		256
43*10001SJoyce.McIntosh@Sun.COM #define	SVCCTL_ENUMSERVICES_MINBUFSIZE	1024
44*10001SJoyce.McIntosh@Sun.COM 
457961SNatalie.Li@Sun.COM #define	SVCCTL_OPENSVC_OP_UNIMPLEMENTED(S)	\
467961SNatalie.Li@Sun.COM 	((S) & SERVICE_CHANGE_CONFIG)	||	\
477961SNatalie.Li@Sun.COM 	((S) & SERVICE_PAUSE_CONTINUE)	||	\
487961SNatalie.Li@Sun.COM 	((S) & SERVICE_START)		||	\
497961SNatalie.Li@Sun.COM 	((S) & SERVICE_STOP)		||	\
507961SNatalie.Li@Sun.COM 	((S) & SERVICE_ENUMERATE_DEPENDENTS)
517961SNatalie.Li@Sun.COM 
528334SJose.Borrego@Sun.COM static int svcctl_s_Close(void *, ndr_xa_t *);
53*10001SJoyce.McIntosh@Sun.COM static int svcctl_s_ControlService(void *, ndr_xa_t *);
54*10001SJoyce.McIntosh@Sun.COM static int svcctl_s_DeleteService(void *, ndr_xa_t *);
55*10001SJoyce.McIntosh@Sun.COM static int svcctl_s_QueryServiceSecurity(void *, ndr_xa_t *);
56*10001SJoyce.McIntosh@Sun.COM static int svcctl_s_SetServiceSecurity(void *, ndr_xa_t *);
578334SJose.Borrego@Sun.COM static int svcctl_s_OpenManager(void *, ndr_xa_t *);
588334SJose.Borrego@Sun.COM static int svcctl_s_OpenService(void *, ndr_xa_t *);
598334SJose.Borrego@Sun.COM static int svcctl_s_QueryServiceStatus(void *, ndr_xa_t *);
608334SJose.Borrego@Sun.COM static int svcctl_s_QueryServiceConfig(void *, ndr_xa_t *);
61*10001SJoyce.McIntosh@Sun.COM static int svcctl_s_StartService(void *, ndr_xa_t *);
62*10001SJoyce.McIntosh@Sun.COM static int svcctl_s_EnumDependentServices(void *, ndr_xa_t *);
638334SJose.Borrego@Sun.COM static int svcctl_s_EnumServicesStatus(void *, ndr_xa_t *);
648334SJose.Borrego@Sun.COM static int svcctl_s_GetServiceDisplayNameW(void *, ndr_xa_t *);
658334SJose.Borrego@Sun.COM static int svcctl_s_GetServiceKeyNameW(void *, ndr_xa_t *);
66*10001SJoyce.McIntosh@Sun.COM static int svcctl_s_OpenSCManagerA(void *, ndr_xa_t *);
67*10001SJoyce.McIntosh@Sun.COM static int svcctl_s_OpenServiceA(void *, ndr_xa_t *);
68*10001SJoyce.McIntosh@Sun.COM static int svcctl_s_EnumServicesStatusA(void *, ndr_xa_t *);
698334SJose.Borrego@Sun.COM static int svcctl_s_QueryServiceConfig2W(void *, ndr_xa_t *);
70*10001SJoyce.McIntosh@Sun.COM static int svcctl_s_QueryServiceStatusEx(void *, ndr_xa_t *);
717961SNatalie.Li@Sun.COM 
728334SJose.Borrego@Sun.COM static ndr_stub_table_t svcctl_stub_table[] = {
737961SNatalie.Li@Sun.COM 	{ svcctl_s_Close,		SVCCTL_OPNUM_Close },
74*10001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_ControlService,	SVCCTL_OPNUM_ControlService },
75*10001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_DeleteService,	SVCCTL_OPNUM_DeleteService },
76*10001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_QueryServiceSecurity, SVCCTL_OPNUM_QueryServiceSecurity },
77*10001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_SetServiceSecurity,	SVCCTL_OPNUM_SetServiceSecurity },
787961SNatalie.Li@Sun.COM 	{ svcctl_s_OpenManager,		SVCCTL_OPNUM_OpenManager },
797961SNatalie.Li@Sun.COM 	{ svcctl_s_OpenService,		SVCCTL_OPNUM_OpenService },
807961SNatalie.Li@Sun.COM 	{ svcctl_s_QueryServiceStatus,	SVCCTL_OPNUM_QueryServiceStatus },
817961SNatalie.Li@Sun.COM 	{ svcctl_s_QueryServiceConfig,	SVCCTL_OPNUM_QueryServiceConfig },
82*10001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_StartService,	SVCCTL_OPNUM_StartService },
83*10001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_EnumDependentServices,
84*10001SJoyce.McIntosh@Sun.COM 		SVCCTL_OPNUM_EnumDependentServices },
857961SNatalie.Li@Sun.COM 	{ svcctl_s_EnumServicesStatus,	SVCCTL_OPNUM_EnumServicesStatus },
867961SNatalie.Li@Sun.COM 	{ svcctl_s_GetServiceDisplayNameW,
877961SNatalie.Li@Sun.COM 		SVCCTL_OPNUM_GetServiceDisplayNameW },
887961SNatalie.Li@Sun.COM 	{ svcctl_s_GetServiceKeyNameW,	SVCCTL_OPNUM_GetServiceKeyNameW },
89*10001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_OpenSCManagerA,	SVCCTL_OPNUM_OpenSCManagerA },
90*10001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_OpenServiceA,	SVCCTL_OPNUM_OpenServiceA },
91*10001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_EnumServicesStatusA,	SVCCTL_OPNUM_EnumServicesStatusA },
927961SNatalie.Li@Sun.COM 	{ svcctl_s_QueryServiceConfig2W, SVCCTL_OPNUM_QueryServiceConfig2W },
93*10001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_QueryServiceStatusEx, SVCCTL_OPNUM_QueryServiceStatusEx },
947961SNatalie.Li@Sun.COM 	{0}
957961SNatalie.Li@Sun.COM };
967961SNatalie.Li@Sun.COM 
978334SJose.Borrego@Sun.COM static ndr_service_t svcctl_service = {
987961SNatalie.Li@Sun.COM 	"SVCCTL",			/* name */
997961SNatalie.Li@Sun.COM 	"Service Control Services",	/* desc */
1007961SNatalie.Li@Sun.COM 	"\\svcctl",			/* endpoint */
1017961SNatalie.Li@Sun.COM 	PIPE_NTSVCS,			/* sec_addr_port */
1028334SJose.Borrego@Sun.COM 	"367abb81-9844-35f1-ad32-98f038001003", 2,	/* abstract */
1038334SJose.Borrego@Sun.COM 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
1047961SNatalie.Li@Sun.COM 	0,				/* no bind_instance_size */
1057961SNatalie.Li@Sun.COM 	0,				/* no bind_req() */
1067961SNatalie.Li@Sun.COM 	0,				/* no unbind_and_close() */
1077961SNatalie.Li@Sun.COM 	0,				/* use generic_call_stub() */
1087961SNatalie.Li@Sun.COM 	&TYPEINFO(svcctl_interface),	/* interface ti */
1097961SNatalie.Li@Sun.COM 	svcctl_stub_table		/* stub_table */
1107961SNatalie.Li@Sun.COM };
1117961SNatalie.Li@Sun.COM 
1127961SNatalie.Li@Sun.COM /*
1137961SNatalie.Li@Sun.COM  * svcctl_initialize
1147961SNatalie.Li@Sun.COM  *
1157961SNatalie.Li@Sun.COM  * This function registers the SVCCTL RPC interface with the RPC runtime
1167961SNatalie.Li@Sun.COM  * library. It must be called in order to use either the client side
1177961SNatalie.Li@Sun.COM  * or the server side functions.
1187961SNatalie.Li@Sun.COM  */
1197961SNatalie.Li@Sun.COM void
1207961SNatalie.Li@Sun.COM svcctl_initialize(void)
1217961SNatalie.Li@Sun.COM {
1228334SJose.Borrego@Sun.COM 	(void) ndr_svc_register(&svcctl_service);
1237961SNatalie.Li@Sun.COM }
1247961SNatalie.Li@Sun.COM 
1257961SNatalie.Li@Sun.COM /*
1267961SNatalie.Li@Sun.COM  * svcctl_hdlookup
1277961SNatalie.Li@Sun.COM  *
1287961SNatalie.Li@Sun.COM  * Handle lookup wrapper to validate the local service and/or manager context.
1297961SNatalie.Li@Sun.COM  */
1307961SNatalie.Li@Sun.COM static ndr_handle_t *
1317961SNatalie.Li@Sun.COM svcctl_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, svcctl_context_type_t type)
1327961SNatalie.Li@Sun.COM {
1337961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
1347961SNatalie.Li@Sun.COM 	svcctl_context_t *ctx;
1357961SNatalie.Li@Sun.COM 
1367961SNatalie.Li@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) == NULL)
1377961SNatalie.Li@Sun.COM 		return (NULL);
1387961SNatalie.Li@Sun.COM 
1397961SNatalie.Li@Sun.COM 	if ((ctx = (svcctl_context_t *)hd->nh_data) == NULL)
1407961SNatalie.Li@Sun.COM 		return (NULL);
1417961SNatalie.Li@Sun.COM 
1427961SNatalie.Li@Sun.COM 	if ((ctx->c_type != type) || (ctx->c_ctx.uc_cp == NULL))
1437961SNatalie.Li@Sun.COM 		return (NULL);
1447961SNatalie.Li@Sun.COM 
1457961SNatalie.Li@Sun.COM 	return (hd);
1467961SNatalie.Li@Sun.COM }
1477961SNatalie.Li@Sun.COM 
1487961SNatalie.Li@Sun.COM /*
1497961SNatalie.Li@Sun.COM  * svcctl_hdfree
1507961SNatalie.Li@Sun.COM  *
1517961SNatalie.Li@Sun.COM  * Handle deallocation wrapper to free the local service and/or manager context.
1527961SNatalie.Li@Sun.COM  */
1537961SNatalie.Li@Sun.COM static void
1547961SNatalie.Li@Sun.COM svcctl_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id)
1557961SNatalie.Li@Sun.COM {
1567961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
1577961SNatalie.Li@Sun.COM 	svcctl_context_t *ctx;
1587961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
1597961SNatalie.Li@Sun.COM 	svcctl_service_context_t *svc_ctx;
1607961SNatalie.Li@Sun.COM 
1617961SNatalie.Li@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
1627961SNatalie.Li@Sun.COM 		ctx = (svcctl_context_t *)hd->nh_data;
1637961SNatalie.Li@Sun.COM 
1647961SNatalie.Li@Sun.COM 		switch (ctx->c_type) {
1657961SNatalie.Li@Sun.COM 		case SVCCTL_MANAGER_CONTEXT:
1667961SNatalie.Li@Sun.COM 			mgr_ctx = ctx->c_ctx.uc_mgr;
1677961SNatalie.Li@Sun.COM 			svcctl_scm_fini(mgr_ctx);
1687961SNatalie.Li@Sun.COM 			svcctl_scm_scf_handle_fini(mgr_ctx);
1697961SNatalie.Li@Sun.COM 			free(mgr_ctx);
1707961SNatalie.Li@Sun.COM 			break;
1717961SNatalie.Li@Sun.COM 
1727961SNatalie.Li@Sun.COM 		case SVCCTL_SERVICE_CONTEXT:
1737961SNatalie.Li@Sun.COM 			svc_ctx = ctx->c_ctx.uc_svc;
1747961SNatalie.Li@Sun.COM 			free(svc_ctx->sc_mgrid);
1757961SNatalie.Li@Sun.COM 			free(svc_ctx->sc_svcname);
1767961SNatalie.Li@Sun.COM 			free(svc_ctx);
1777961SNatalie.Li@Sun.COM 			break;
1787961SNatalie.Li@Sun.COM 
1797961SNatalie.Li@Sun.COM 		default:
1807961SNatalie.Li@Sun.COM 			break;
1817961SNatalie.Li@Sun.COM 		}
1827961SNatalie.Li@Sun.COM 
1837961SNatalie.Li@Sun.COM 		free(ctx);
1847961SNatalie.Li@Sun.COM 		ndr_hdfree(mxa, id);
1857961SNatalie.Li@Sun.COM 	}
1867961SNatalie.Li@Sun.COM }
1877961SNatalie.Li@Sun.COM 
1887961SNatalie.Li@Sun.COM /*
1897961SNatalie.Li@Sun.COM  * svcctl_mgr_hdalloc
1907961SNatalie.Li@Sun.COM  *
1917961SNatalie.Li@Sun.COM  * Handle allocation wrapper to setup the local manager context.
1927961SNatalie.Li@Sun.COM  */
1937961SNatalie.Li@Sun.COM static ndr_hdid_t *
1947961SNatalie.Li@Sun.COM svcctl_mgr_hdalloc(ndr_xa_t *mxa)
1957961SNatalie.Li@Sun.COM {
1967961SNatalie.Li@Sun.COM 	svcctl_context_t *ctx;
1977961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
1987961SNatalie.Li@Sun.COM 
1997961SNatalie.Li@Sun.COM 	if ((ctx = malloc(sizeof (svcctl_context_t))) == NULL)
2007961SNatalie.Li@Sun.COM 		return (NULL);
2017961SNatalie.Li@Sun.COM 	ctx->c_type = SVCCTL_MANAGER_CONTEXT;
2027961SNatalie.Li@Sun.COM 
2037961SNatalie.Li@Sun.COM 	if ((mgr_ctx = malloc(sizeof (svcctl_manager_context_t))) == NULL) {
2047961SNatalie.Li@Sun.COM 		free(ctx);
2057961SNatalie.Li@Sun.COM 		return (NULL);
2067961SNatalie.Li@Sun.COM 	}
2077961SNatalie.Li@Sun.COM 	bzero(mgr_ctx, sizeof (svcctl_manager_context_t));
2087961SNatalie.Li@Sun.COM 
2097961SNatalie.Li@Sun.COM 	if (svcctl_scm_scf_handle_init(mgr_ctx) < 0) {
2107961SNatalie.Li@Sun.COM 		free(mgr_ctx);
2117961SNatalie.Li@Sun.COM 		free(ctx);
2127961SNatalie.Li@Sun.COM 		return (NULL);
2137961SNatalie.Li@Sun.COM 	}
2147961SNatalie.Li@Sun.COM 
2157961SNatalie.Li@Sun.COM 	if (svcctl_scm_init(mgr_ctx) < 0) {
2167961SNatalie.Li@Sun.COM 		svcctl_scm_scf_handle_fini(mgr_ctx);
2177961SNatalie.Li@Sun.COM 		free(mgr_ctx);
2187961SNatalie.Li@Sun.COM 		free(ctx);
2197961SNatalie.Li@Sun.COM 		return (NULL);
2207961SNatalie.Li@Sun.COM 	}
2217961SNatalie.Li@Sun.COM 
2227961SNatalie.Li@Sun.COM 	ctx->c_ctx.uc_mgr = mgr_ctx;
2237961SNatalie.Li@Sun.COM 
2247961SNatalie.Li@Sun.COM 	return (ndr_hdalloc(mxa, ctx));
2257961SNatalie.Li@Sun.COM }
2267961SNatalie.Li@Sun.COM 
2277961SNatalie.Li@Sun.COM /*
2287961SNatalie.Li@Sun.COM  * svcctl_get_mgr_ctx
2297961SNatalie.Li@Sun.COM  *
2307961SNatalie.Li@Sun.COM  * This function looks up a reference to local manager context.
2317961SNatalie.Li@Sun.COM  */
2327961SNatalie.Li@Sun.COM static svcctl_manager_context_t *
2337961SNatalie.Li@Sun.COM svcctl_get_mgr_ctx(ndr_xa_t *mxa, ndr_hdid_t *mgr_id)
2347961SNatalie.Li@Sun.COM {
2357961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
2367961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
2377961SNatalie.Li@Sun.COM 
2387961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, mgr_id, SVCCTL_MANAGER_CONTEXT);
2397961SNatalie.Li@Sun.COM 	if (hd == NULL)
2407961SNatalie.Li@Sun.COM 		return (NULL);
2417961SNatalie.Li@Sun.COM 
2427961SNatalie.Li@Sun.COM 	mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr;
2437961SNatalie.Li@Sun.COM 
2447961SNatalie.Li@Sun.COM 	return (mgr_ctx);
2457961SNatalie.Li@Sun.COM }
2467961SNatalie.Li@Sun.COM 
2477961SNatalie.Li@Sun.COM /*
2487961SNatalie.Li@Sun.COM  * svcctl_svc_hdalloc
2497961SNatalie.Li@Sun.COM  *
2507961SNatalie.Li@Sun.COM  * Handle allocation wrapper to setup the local service context.
2517961SNatalie.Li@Sun.COM  */
2527961SNatalie.Li@Sun.COM static ndr_hdid_t *
2537961SNatalie.Li@Sun.COM svcctl_svc_hdalloc(ndr_xa_t *mxa, ndr_hdid_t *mgr_id, char *svc_name)
2547961SNatalie.Li@Sun.COM {
2557961SNatalie.Li@Sun.COM 	svcctl_context_t *ctx;
2567961SNatalie.Li@Sun.COM 	svcctl_service_context_t *svc_ctx;
2577961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
2587961SNatalie.Li@Sun.COM 	int max_name_sz = 0;
2597961SNatalie.Li@Sun.COM 	char *svcname;
2607961SNatalie.Li@Sun.COM 
2617961SNatalie.Li@Sun.COM 	mgr_ctx = svcctl_get_mgr_ctx(mxa, mgr_id);
2627961SNatalie.Li@Sun.COM 	if (mgr_ctx == NULL)
2637961SNatalie.Li@Sun.COM 		return (NULL);
2647961SNatalie.Li@Sun.COM 	max_name_sz = mgr_ctx->mc_scf_max_fmri_len;
2657961SNatalie.Li@Sun.COM 
2667961SNatalie.Li@Sun.COM 	if ((ctx = malloc(sizeof (svcctl_context_t))) == NULL) {
2677961SNatalie.Li@Sun.COM 		svcctl_hdfree(mxa, mgr_id);
2687961SNatalie.Li@Sun.COM 		return (NULL);
2697961SNatalie.Li@Sun.COM 	}
2707961SNatalie.Li@Sun.COM 	ctx->c_type = SVCCTL_SERVICE_CONTEXT;
2717961SNatalie.Li@Sun.COM 
2727961SNatalie.Li@Sun.COM 	if ((svc_ctx = malloc(sizeof (svcctl_service_context_t))) == NULL) {
2737961SNatalie.Li@Sun.COM 		svcctl_hdfree(mxa, mgr_id);
2747961SNatalie.Li@Sun.COM 		free(ctx);
2757961SNatalie.Li@Sun.COM 		return (NULL);
2767961SNatalie.Li@Sun.COM 	}
2777961SNatalie.Li@Sun.COM 	bzero(svc_ctx, sizeof (svcctl_service_context_t));
2787961SNatalie.Li@Sun.COM 
2797961SNatalie.Li@Sun.COM 	svc_ctx->sc_mgrid = malloc(sizeof (ndr_hdid_t));
2807961SNatalie.Li@Sun.COM 	svcname = malloc(max_name_sz);
2817961SNatalie.Li@Sun.COM 
2827961SNatalie.Li@Sun.COM 	if ((svc_ctx->sc_mgrid == NULL) || (svcname == NULL)) {
2837961SNatalie.Li@Sun.COM 		free(svc_ctx->sc_mgrid);
2847961SNatalie.Li@Sun.COM 		free(svc_ctx);
2857961SNatalie.Li@Sun.COM 		svcctl_hdfree(mxa, mgr_id);
2867961SNatalie.Li@Sun.COM 		free(ctx);
2877961SNatalie.Li@Sun.COM 		return (NULL);
2887961SNatalie.Li@Sun.COM 	}
2897961SNatalie.Li@Sun.COM 
2907961SNatalie.Li@Sun.COM 	svc_ctx->sc_svcname = svcname;
2917961SNatalie.Li@Sun.COM 
2927961SNatalie.Li@Sun.COM 	bcopy(mgr_id, svc_ctx->sc_mgrid, sizeof (ndr_hdid_t));
2937961SNatalie.Li@Sun.COM 	(void) strlcpy(svc_ctx->sc_svcname, svc_name, max_name_sz);
2947961SNatalie.Li@Sun.COM 
2957961SNatalie.Li@Sun.COM 	ctx->c_ctx.uc_svc = svc_ctx;
2967961SNatalie.Li@Sun.COM 
2977961SNatalie.Li@Sun.COM 	return (ndr_hdalloc(mxa, ctx));
2987961SNatalie.Li@Sun.COM }
2997961SNatalie.Li@Sun.COM 
3007961SNatalie.Li@Sun.COM /*
3017961SNatalie.Li@Sun.COM  * svcctl_s_Close
3027961SNatalie.Li@Sun.COM  *
3037961SNatalie.Li@Sun.COM  * This is a request to close the SVCCTL interface specified by the
3047961SNatalie.Li@Sun.COM  * handle. Free the handle and zero out the result handle for the
3057961SNatalie.Li@Sun.COM  * client.
3067961SNatalie.Li@Sun.COM  *
3077961SNatalie.Li@Sun.COM  * Returns:
3087961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
3097961SNatalie.Li@Sun.COM  *	ERROR_INVALID_HANDLE
3107961SNatalie.Li@Sun.COM  */
3117961SNatalie.Li@Sun.COM static int
3128334SJose.Borrego@Sun.COM svcctl_s_Close(void *arg, ndr_xa_t *mxa)
3137961SNatalie.Li@Sun.COM {
3147961SNatalie.Li@Sun.COM 	struct svcctl_Close *param = arg;
3157961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
3167961SNatalie.Li@Sun.COM 
3177961SNatalie.Li@Sun.COM 	svcctl_hdfree(mxa, id);
3187961SNatalie.Li@Sun.COM 
3197961SNatalie.Li@Sun.COM 	bzero(&param->result_handle, sizeof (svcctl_handle_t));
3207961SNatalie.Li@Sun.COM 	param->status = ERROR_SUCCESS;
3218334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
3227961SNatalie.Li@Sun.COM }
3237961SNatalie.Li@Sun.COM 
3247961SNatalie.Li@Sun.COM /*
325*10001SJoyce.McIntosh@Sun.COM  * svcctl_s_ControlService
326*10001SJoyce.McIntosh@Sun.COM  */
327*10001SJoyce.McIntosh@Sun.COM static int
328*10001SJoyce.McIntosh@Sun.COM svcctl_s_ControlService(void *arg, ndr_xa_t *mxa)
329*10001SJoyce.McIntosh@Sun.COM {
330*10001SJoyce.McIntosh@Sun.COM 	struct svcctl_ControlService *param = arg;
331*10001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
332*10001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
333*10001SJoyce.McIntosh@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
334*10001SJoyce.McIntosh@Sun.COM 	svcctl_service_context_t *svc_ctx;
335*10001SJoyce.McIntosh@Sun.COM 	svcctl_svc_node_t *svc;
336*10001SJoyce.McIntosh@Sun.COM 
337*10001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
338*10001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
339*10001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_ControlService));
340*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
341*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
342*10001SJoyce.McIntosh@Sun.COM 	}
343*10001SJoyce.McIntosh@Sun.COM 
344*10001SJoyce.McIntosh@Sun.COM 	svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc;
345*10001SJoyce.McIntosh@Sun.COM 	mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid);
346*10001SJoyce.McIntosh@Sun.COM 	if (mgr_ctx == NULL) {
347*10001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_ControlService));
348*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
349*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
350*10001SJoyce.McIntosh@Sun.COM 	}
351*10001SJoyce.McIntosh@Sun.COM 
352*10001SJoyce.McIntosh@Sun.COM 	switch (param->control) {
353*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_STOP:
354*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_PAUSE:
355*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_CONTINUE:
356*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_INTERROGATE:
357*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_SHUTDOWN:
358*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_PARAMCHANGE:
359*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_NETBINDADD:
360*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_NETBINDREMOVE:
361*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_NETBINDENABLE:
362*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_NETBINDDISABLE:
363*10001SJoyce.McIntosh@Sun.COM 		break;
364*10001SJoyce.McIntosh@Sun.COM 	default:
365*10001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_ControlService));
366*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_PARAMETER;
367*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
368*10001SJoyce.McIntosh@Sun.COM 	}
369*10001SJoyce.McIntosh@Sun.COM 
370*10001SJoyce.McIntosh@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname);
371*10001SJoyce.McIntosh@Sun.COM 	if (svc == NULL || svc->sn_state == NULL) {
372*10001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_ControlService));
373*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_SERVICE_DOES_NOT_EXIST;
374*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
375*10001SJoyce.McIntosh@Sun.COM 	}
376*10001SJoyce.McIntosh@Sun.COM 
377*10001SJoyce.McIntosh@Sun.COM 	param->service_status.service_type = SERVICE_WIN32_SHARE_PROCESS;
378*10001SJoyce.McIntosh@Sun.COM 	param->service_status.cur_state = svcctl_scm_map_status(svc->sn_state);
379*10001SJoyce.McIntosh@Sun.COM 	param->service_status.ctrl_accepted = 0;
380*10001SJoyce.McIntosh@Sun.COM 	param->service_status.w32_exitcode = 0;
381*10001SJoyce.McIntosh@Sun.COM 	param->service_status.svc_specified_exitcode = 0;
382*10001SJoyce.McIntosh@Sun.COM 	param->service_status.check_point = 0;
383*10001SJoyce.McIntosh@Sun.COM 	param->service_status.wait_hint = 0;
384*10001SJoyce.McIntosh@Sun.COM 
385*10001SJoyce.McIntosh@Sun.COM 	param->status = ERROR_SUCCESS;
386*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
387*10001SJoyce.McIntosh@Sun.COM }
388*10001SJoyce.McIntosh@Sun.COM 
389*10001SJoyce.McIntosh@Sun.COM /*
390*10001SJoyce.McIntosh@Sun.COM  * svcctl_s_DeleteService
391*10001SJoyce.McIntosh@Sun.COM  */
392*10001SJoyce.McIntosh@Sun.COM static int
393*10001SJoyce.McIntosh@Sun.COM svcctl_s_DeleteService(void *arg, ndr_xa_t *mxa)
394*10001SJoyce.McIntosh@Sun.COM {
395*10001SJoyce.McIntosh@Sun.COM 	struct svcctl_DeleteService *param = arg;
396*10001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
397*10001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
398*10001SJoyce.McIntosh@Sun.COM 
399*10001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
400*10001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
401*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
402*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
403*10001SJoyce.McIntosh@Sun.COM 	}
404*10001SJoyce.McIntosh@Sun.COM 
405*10001SJoyce.McIntosh@Sun.COM 	param->status = ERROR_SUCCESS;
406*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
407*10001SJoyce.McIntosh@Sun.COM }
408*10001SJoyce.McIntosh@Sun.COM 
409*10001SJoyce.McIntosh@Sun.COM /*
410*10001SJoyce.McIntosh@Sun.COM  * svcctl_s_QueryServiceSecurity
411*10001SJoyce.McIntosh@Sun.COM  */
412*10001SJoyce.McIntosh@Sun.COM static int
413*10001SJoyce.McIntosh@Sun.COM svcctl_s_QueryServiceSecurity(void *arg, ndr_xa_t *mxa)
414*10001SJoyce.McIntosh@Sun.COM {
415*10001SJoyce.McIntosh@Sun.COM 	struct svcctl_QueryServiceSecurity *param = arg;
416*10001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
417*10001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
418*10001SJoyce.McIntosh@Sun.COM 	uint32_t sec_info;
419*10001SJoyce.McIntosh@Sun.COM 	uint32_t bytes_needed = 0;
420*10001SJoyce.McIntosh@Sun.COM 	uint32_t status;
421*10001SJoyce.McIntosh@Sun.COM 
422*10001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
423*10001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
424*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
425*10001SJoyce.McIntosh@Sun.COM 		goto query_service_security_error;
426*10001SJoyce.McIntosh@Sun.COM 	}
427*10001SJoyce.McIntosh@Sun.COM 
428*10001SJoyce.McIntosh@Sun.COM 	sec_info = param->security_info & SMB_ALL_SECINFO;
429*10001SJoyce.McIntosh@Sun.COM 	if (sec_info == 0) {
430*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_PARAMETER;
431*10001SJoyce.McIntosh@Sun.COM 		goto query_service_security_error;
432*10001SJoyce.McIntosh@Sun.COM 	}
433*10001SJoyce.McIntosh@Sun.COM 
434*10001SJoyce.McIntosh@Sun.COM 	if (param->buf_size < SVCCTL_SECURITY_BUFSIZE) {
435*10001SJoyce.McIntosh@Sun.COM 		bytes_needed = SVCCTL_SECURITY_BUFSIZE;
436*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_INSUFFICIENT_BUFFER;
437*10001SJoyce.McIntosh@Sun.COM 		goto query_service_security_error;
438*10001SJoyce.McIntosh@Sun.COM 	}
439*10001SJoyce.McIntosh@Sun.COM 
440*10001SJoyce.McIntosh@Sun.COM 	param->buffer = NDR_MALLOC(mxa, SVCCTL_SECURITY_BUFSIZE);
441*10001SJoyce.McIntosh@Sun.COM 	if (param->buffer == NULL) {
442*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
443*10001SJoyce.McIntosh@Sun.COM 		goto query_service_security_error;
444*10001SJoyce.McIntosh@Sun.COM 	}
445*10001SJoyce.McIntosh@Sun.COM 
446*10001SJoyce.McIntosh@Sun.COM 	bzero(param->buffer, sizeof (SVCCTL_SECURITY_BUFSIZE));
447*10001SJoyce.McIntosh@Sun.COM 	param->buf_size = SVCCTL_SECURITY_BUFSIZE;
448*10001SJoyce.McIntosh@Sun.COM 	param->bytes_needed = 0;
449*10001SJoyce.McIntosh@Sun.COM 	param->status = ERROR_SUCCESS;
450*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
451*10001SJoyce.McIntosh@Sun.COM 
452*10001SJoyce.McIntosh@Sun.COM query_service_security_error:
453*10001SJoyce.McIntosh@Sun.COM 	bzero(param, sizeof (struct svcctl_QueryServiceSecurity));
454*10001SJoyce.McIntosh@Sun.COM 	param->buf_size = 0;
455*10001SJoyce.McIntosh@Sun.COM 	param->buffer = NDR_MALLOC(mxa, sizeof (uint32_t));
456*10001SJoyce.McIntosh@Sun.COM 	param->bytes_needed = bytes_needed;
457*10001SJoyce.McIntosh@Sun.COM 	param->status = status;
458*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
459*10001SJoyce.McIntosh@Sun.COM }
460*10001SJoyce.McIntosh@Sun.COM 
461*10001SJoyce.McIntosh@Sun.COM 
462*10001SJoyce.McIntosh@Sun.COM /*
463*10001SJoyce.McIntosh@Sun.COM  * svcctl_s_SetServiceSecurity
464*10001SJoyce.McIntosh@Sun.COM  */
465*10001SJoyce.McIntosh@Sun.COM static int
466*10001SJoyce.McIntosh@Sun.COM svcctl_s_SetServiceSecurity(void *arg, ndr_xa_t *mxa)
467*10001SJoyce.McIntosh@Sun.COM {
468*10001SJoyce.McIntosh@Sun.COM 	struct svcctl_SetServiceSecurity *param = arg;
469*10001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
470*10001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
471*10001SJoyce.McIntosh@Sun.COM 
472*10001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
473*10001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
474*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
475*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
476*10001SJoyce.McIntosh@Sun.COM 	}
477*10001SJoyce.McIntosh@Sun.COM 
478*10001SJoyce.McIntosh@Sun.COM 	if ((param->security_info & SMB_ALL_SECINFO) == 0) {
479*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_PARAMETER;
480*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
481*10001SJoyce.McIntosh@Sun.COM 	}
482*10001SJoyce.McIntosh@Sun.COM 
483*10001SJoyce.McIntosh@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
484*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
485*10001SJoyce.McIntosh@Sun.COM }
486*10001SJoyce.McIntosh@Sun.COM 
487*10001SJoyce.McIntosh@Sun.COM /*
4887961SNatalie.Li@Sun.COM  * svcctl_s_OpenManager
4897961SNatalie.Li@Sun.COM  *
4907961SNatalie.Li@Sun.COM  * Request to open the service control manager.
4917961SNatalie.Li@Sun.COM  * The caller must have administrator rights in order to open this
4927961SNatalie.Li@Sun.COM  * interface.  We don't support write (SC_MANAGER_LOCK) access.
4937961SNatalie.Li@Sun.COM  *
4947961SNatalie.Li@Sun.COM  * Returns:
4957961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
4967961SNatalie.Li@Sun.COM  *	ERROR_ACCESS_DENIED
4977961SNatalie.Li@Sun.COM  *
4987961SNatalie.Li@Sun.COM  * On success, returns a handle for use with subsequent svcctl requests.
4997961SNatalie.Li@Sun.COM  */
5007961SNatalie.Li@Sun.COM static int
5018334SJose.Borrego@Sun.COM svcctl_s_OpenManager(void *arg, ndr_xa_t *mxa)
5027961SNatalie.Li@Sun.COM {
5037961SNatalie.Li@Sun.COM 	struct svcctl_OpenManager *param = arg;
5047961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = NULL;
5057961SNatalie.Li@Sun.COM 	int rc;
5067961SNatalie.Li@Sun.COM 
5077961SNatalie.Li@Sun.COM 	rc = ndr_is_admin(mxa);
5087961SNatalie.Li@Sun.COM 
5097961SNatalie.Li@Sun.COM 	if ((rc == 0) || (param->desired_access & SC_MANAGER_LOCK) != 0) {
5107961SNatalie.Li@Sun.COM 		bzero(&param->handle, sizeof (svcctl_handle_t));
5117961SNatalie.Li@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
5128334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5137961SNatalie.Li@Sun.COM 	}
5147961SNatalie.Li@Sun.COM 
5157961SNatalie.Li@Sun.COM 	id = svcctl_mgr_hdalloc(mxa);
5167961SNatalie.Li@Sun.COM 	if (id) {
5177961SNatalie.Li@Sun.COM 		bcopy(id, &param->handle, sizeof (svcctl_handle_t));
5187961SNatalie.Li@Sun.COM 		param->status = ERROR_SUCCESS;
5197961SNatalie.Li@Sun.COM 	} else {
5207961SNatalie.Li@Sun.COM 		bzero(&param->handle, sizeof (svcctl_handle_t));
5217961SNatalie.Li@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
5227961SNatalie.Li@Sun.COM 	}
5237961SNatalie.Li@Sun.COM 
5248334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
5257961SNatalie.Li@Sun.COM }
5267961SNatalie.Li@Sun.COM 
5277961SNatalie.Li@Sun.COM /*
5287961SNatalie.Li@Sun.COM  * svcctl_s_OpenService
5297961SNatalie.Li@Sun.COM  *
5307961SNatalie.Li@Sun.COM  * Return a handle for use with subsequent svcctl requests.
5317961SNatalie.Li@Sun.COM  *
5327961SNatalie.Li@Sun.COM  * Returns:
5337961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
5347961SNatalie.Li@Sun.COM  *	ERROR_INVALID_HANDLE
5357961SNatalie.Li@Sun.COM  *	ERROR_SERVICE_DOES_NOT_EXIST
5367961SNatalie.Li@Sun.COM  *	ERROR_CALL_NOT_IMPLEMENTED
5377961SNatalie.Li@Sun.COM  */
5387961SNatalie.Li@Sun.COM static int
5398334SJose.Borrego@Sun.COM svcctl_s_OpenService(void *arg, ndr_xa_t *mxa)
5407961SNatalie.Li@Sun.COM {
5417961SNatalie.Li@Sun.COM 	struct svcctl_OpenService *param = arg;
5427961SNatalie.Li@Sun.COM 	ndr_hdid_t *mgrid = (ndr_hdid_t *)&param->manager_handle;
5437961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = NULL;
5447961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
5457961SNatalie.Li@Sun.COM 	DWORD status;
5467961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
5477961SNatalie.Li@Sun.COM 	char *svc_name = (char *)param->service_name;
5487961SNatalie.Li@Sun.COM 	boolean_t unimplemented_operations = B_FALSE;
5497961SNatalie.Li@Sun.COM 
5507961SNatalie.Li@Sun.COM 	/* Allow service handle allocations for only status & config queries */
5517961SNatalie.Li@Sun.COM 	unimplemented_operations =
5527961SNatalie.Li@Sun.COM 	    SVCCTL_OPENSVC_OP_UNIMPLEMENTED(param->desired_access);
5537961SNatalie.Li@Sun.COM 
5547961SNatalie.Li@Sun.COM 	if (unimplemented_operations) {
5557961SNatalie.Li@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
5567961SNatalie.Li@Sun.COM 		param->status = ERROR_CALL_NOT_IMPLEMENTED;
5578334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5587961SNatalie.Li@Sun.COM 	}
5597961SNatalie.Li@Sun.COM 
5607961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, mgrid, SVCCTL_MANAGER_CONTEXT);
5617961SNatalie.Li@Sun.COM 	if (hd == NULL) {
5627961SNatalie.Li@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
5637961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
5648334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5657961SNatalie.Li@Sun.COM 	}
5667961SNatalie.Li@Sun.COM 
5677961SNatalie.Li@Sun.COM 	mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr;
5687961SNatalie.Li@Sun.COM 	status = svcctl_scm_validate_service(mgr_ctx, svc_name);
5697961SNatalie.Li@Sun.COM 	if (status != ERROR_SUCCESS) {
5707961SNatalie.Li@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
5717961SNatalie.Li@Sun.COM 		param->status = status;
5728334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5737961SNatalie.Li@Sun.COM 	}
5747961SNatalie.Li@Sun.COM 
5757961SNatalie.Li@Sun.COM 	id = svcctl_svc_hdalloc(mxa, mgrid, svc_name);
5767961SNatalie.Li@Sun.COM 	if (id) {
5777961SNatalie.Li@Sun.COM 		bcopy(id, &param->service_handle, sizeof (svcctl_handle_t));
5787961SNatalie.Li@Sun.COM 		param->status = ERROR_SUCCESS;
5797961SNatalie.Li@Sun.COM 	} else {
5807961SNatalie.Li@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
5817961SNatalie.Li@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
5827961SNatalie.Li@Sun.COM 	}
5837961SNatalie.Li@Sun.COM 
5848334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
5857961SNatalie.Li@Sun.COM }
5867961SNatalie.Li@Sun.COM 
5877961SNatalie.Li@Sun.COM /*
5887961SNatalie.Li@Sun.COM  * svcctl_s_QueryServiceStatus
5897961SNatalie.Li@Sun.COM  *
5907961SNatalie.Li@Sun.COM  * Returns:
5917961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
5927961SNatalie.Li@Sun.COM  *	ERROR_INVALID_HANDLE
5937961SNatalie.Li@Sun.COM  */
5947961SNatalie.Li@Sun.COM static int
5958334SJose.Borrego@Sun.COM svcctl_s_QueryServiceStatus(void *arg, ndr_xa_t *mxa)
5967961SNatalie.Li@Sun.COM {
5977961SNatalie.Li@Sun.COM 	struct svcctl_QueryServiceStatus *param = arg;
5987961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
5997961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
6007961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
6017961SNatalie.Li@Sun.COM 	svcctl_service_context_t *svc_ctx;
6027961SNatalie.Li@Sun.COM 	svcctl_svc_node_t *svc;
6037961SNatalie.Li@Sun.COM 
6047961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
6057961SNatalie.Li@Sun.COM 	if (hd == NULL) {
6067961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceStatus));
6077961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
6088334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6097961SNatalie.Li@Sun.COM 	}
6107961SNatalie.Li@Sun.COM 
6117961SNatalie.Li@Sun.COM 	svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc;
6127961SNatalie.Li@Sun.COM 	mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid);
6137961SNatalie.Li@Sun.COM 	if (mgr_ctx == NULL) {
614*10001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceStatus));
6157961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
6168334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6177961SNatalie.Li@Sun.COM 	}
6187961SNatalie.Li@Sun.COM 
6197961SNatalie.Li@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname);
6207961SNatalie.Li@Sun.COM 	if (svc == NULL || svc->sn_state == NULL) {
621*10001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceStatus));
6227961SNatalie.Li@Sun.COM 		param->status = ERROR_SERVICE_DOES_NOT_EXIST;
6238334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6247961SNatalie.Li@Sun.COM 	}
6257961SNatalie.Li@Sun.COM 
6267961SNatalie.Li@Sun.COM 	param->service_status.service_type = SERVICE_WIN32_SHARE_PROCESS;
6277961SNatalie.Li@Sun.COM 	param->service_status.cur_state = svcctl_scm_map_status(svc->sn_state);
6287961SNatalie.Li@Sun.COM 	param->service_status.ctrl_accepted = 0;
6297961SNatalie.Li@Sun.COM 	param->service_status.w32_exitcode = 0;
6307961SNatalie.Li@Sun.COM 	param->service_status.svc_specified_exitcode = 0;
6317961SNatalie.Li@Sun.COM 	param->service_status.check_point = 0;
6327961SNatalie.Li@Sun.COM 	param->service_status.wait_hint = 0;
6337961SNatalie.Li@Sun.COM 
6347961SNatalie.Li@Sun.COM 	param->status = ERROR_SUCCESS;
6358334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6367961SNatalie.Li@Sun.COM }
6377961SNatalie.Li@Sun.COM 
6387961SNatalie.Li@Sun.COM /*
639*10001SJoyce.McIntosh@Sun.COM  * svcctl_s_EnumDependentServices
640*10001SJoyce.McIntosh@Sun.COM  *
641*10001SJoyce.McIntosh@Sun.COM  * Enumerate the list of services that depend on the specified service.
642*10001SJoyce.McIntosh@Sun.COM  */
643*10001SJoyce.McIntosh@Sun.COM static int
644*10001SJoyce.McIntosh@Sun.COM svcctl_s_EnumDependentServices(void *arg, ndr_xa_t *mxa)
645*10001SJoyce.McIntosh@Sun.COM {
646*10001SJoyce.McIntosh@Sun.COM 	struct svcctl_EnumDependentServices *param = arg;
647*10001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
648*10001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
649*10001SJoyce.McIntosh@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
650*10001SJoyce.McIntosh@Sun.COM 	svcctl_service_context_t *svc_ctx;
651*10001SJoyce.McIntosh@Sun.COM 	svcctl_svc_node_t *svc;
652*10001SJoyce.McIntosh@Sun.COM 	int input_bufsize = 0;
653*10001SJoyce.McIntosh@Sun.COM 	uint32_t status;
654*10001SJoyce.McIntosh@Sun.COM 
655*10001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
656*10001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
657*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
658*10001SJoyce.McIntosh@Sun.COM 		goto enum_dependent_services_error;
659*10001SJoyce.McIntosh@Sun.COM 	}
660*10001SJoyce.McIntosh@Sun.COM 
661*10001SJoyce.McIntosh@Sun.COM 	svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc;
662*10001SJoyce.McIntosh@Sun.COM 	mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid);
663*10001SJoyce.McIntosh@Sun.COM 	if (mgr_ctx == NULL) {
664*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
665*10001SJoyce.McIntosh@Sun.COM 		goto enum_dependent_services_error;
666*10001SJoyce.McIntosh@Sun.COM 	}
667*10001SJoyce.McIntosh@Sun.COM 
668*10001SJoyce.McIntosh@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname);
669*10001SJoyce.McIntosh@Sun.COM 	if (svc == NULL || svc->sn_state == NULL) {
670*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_SERVICE_DOES_NOT_EXIST;
671*10001SJoyce.McIntosh@Sun.COM 		goto enum_dependent_services_error;
672*10001SJoyce.McIntosh@Sun.COM 	}
673*10001SJoyce.McIntosh@Sun.COM 
674*10001SJoyce.McIntosh@Sun.COM 	switch (param->svc_state) {
675*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_STOPPED:
676*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_START_PENDING:
677*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_STOP_PENDING:
678*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_RUNNING:
679*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTINUE_PENDING:
680*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_PAUSE_PENDING:
681*10001SJoyce.McIntosh@Sun.COM 	case SERVICE_PAUSED:
682*10001SJoyce.McIntosh@Sun.COM 		break;
683*10001SJoyce.McIntosh@Sun.COM 	default:
684*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_PARAMETER;
685*10001SJoyce.McIntosh@Sun.COM 		goto enum_dependent_services_error;
686*10001SJoyce.McIntosh@Sun.COM 	}
687*10001SJoyce.McIntosh@Sun.COM 
688*10001SJoyce.McIntosh@Sun.COM 	if ((input_bufsize = param->buf_size) == 0) {
689*10001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_EnumDependentServices));
690*10001SJoyce.McIntosh@Sun.COM 		param->buf_size = input_bufsize;
691*10001SJoyce.McIntosh@Sun.COM 		param->services = NDR_STRDUP(mxa, "");
692*10001SJoyce.McIntosh@Sun.COM 		param->bytes_needed = 1024;
693*10001SJoyce.McIntosh@Sun.COM 		param->svc_num = 0;
694*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_MORE_DATA;
695*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
696*10001SJoyce.McIntosh@Sun.COM 	}
697*10001SJoyce.McIntosh@Sun.COM 
698*10001SJoyce.McIntosh@Sun.COM 	param->services = NDR_MALLOC(mxa, input_bufsize);
699*10001SJoyce.McIntosh@Sun.COM 	if (param->services == NULL) {
700*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
701*10001SJoyce.McIntosh@Sun.COM 		goto enum_dependent_services_error;
702*10001SJoyce.McIntosh@Sun.COM 	}
703*10001SJoyce.McIntosh@Sun.COM 
704*10001SJoyce.McIntosh@Sun.COM 	bzero(param->services, input_bufsize);
705*10001SJoyce.McIntosh@Sun.COM 	param->buf_size = input_bufsize;
706*10001SJoyce.McIntosh@Sun.COM 	param->bytes_needed = 0;
707*10001SJoyce.McIntosh@Sun.COM 	param->svc_num = 0;
708*10001SJoyce.McIntosh@Sun.COM 	param->status = ERROR_SUCCESS;
709*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
710*10001SJoyce.McIntosh@Sun.COM 
711*10001SJoyce.McIntosh@Sun.COM enum_dependent_services_error:
712*10001SJoyce.McIntosh@Sun.COM 	bzero(param, sizeof (struct svcctl_EnumDependentServices));
713*10001SJoyce.McIntosh@Sun.COM 	param->services = NDR_STRDUP(mxa, "");
714*10001SJoyce.McIntosh@Sun.COM 	param->status = status;
715*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
716*10001SJoyce.McIntosh@Sun.COM }
717*10001SJoyce.McIntosh@Sun.COM 
718*10001SJoyce.McIntosh@Sun.COM /*
7197961SNatalie.Li@Sun.COM  * svcctl_s_EnumServicesStatus
7207961SNatalie.Li@Sun.COM  *
721*10001SJoyce.McIntosh@Sun.COM  * Enumerate the list of services we support.
7227961SNatalie.Li@Sun.COM  */
7237961SNatalie.Li@Sun.COM static int
7248334SJose.Borrego@Sun.COM svcctl_s_EnumServicesStatus(void *arg, ndr_xa_t *mxa)
7257961SNatalie.Li@Sun.COM {
7267961SNatalie.Li@Sun.COM 	struct svcctl_EnumServicesStatus *param = arg;
7277961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->manager_handle;
7287961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
7297961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
730*10001SJoyce.McIntosh@Sun.COM 	uint32_t buf_size = 0;
731*10001SJoyce.McIntosh@Sun.COM 	uint32_t svc_num;
732*10001SJoyce.McIntosh@Sun.COM 	uint32_t resume_handle = 0;
733*10001SJoyce.McIntosh@Sun.COM 	uint32_t status;
734*10001SJoyce.McIntosh@Sun.COM 
735*10001SJoyce.McIntosh@Sun.COM 	if (param->resume_handle != NULL)
736*10001SJoyce.McIntosh@Sun.COM 		resume_handle = *param->resume_handle;
7377961SNatalie.Li@Sun.COM 
7387961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_MANAGER_CONTEXT);
7397961SNatalie.Li@Sun.COM 	if (hd == NULL) {
740*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
741*10001SJoyce.McIntosh@Sun.COM 		goto enum_services_status_error;
7427961SNatalie.Li@Sun.COM 	}
7437961SNatalie.Li@Sun.COM 
7447961SNatalie.Li@Sun.COM 	mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr;
7457961SNatalie.Li@Sun.COM 	if (svcctl_scm_refresh(mgr_ctx) != 0) {
746*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
747*10001SJoyce.McIntosh@Sun.COM 		goto enum_services_status_error;
7487961SNatalie.Li@Sun.COM 	}
7497961SNatalie.Li@Sun.COM 
750*10001SJoyce.McIntosh@Sun.COM 	buf_size = param->buf_size;
751*10001SJoyce.McIntosh@Sun.COM 	param->services = NDR_MALLOC(mxa, buf_size);
7527961SNatalie.Li@Sun.COM 	if (param->services == NULL) {
753*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
754*10001SJoyce.McIntosh@Sun.COM 		goto enum_services_status_error;
7557961SNatalie.Li@Sun.COM 	}
756*10001SJoyce.McIntosh@Sun.COM 	bzero(param->services, buf_size);
7577961SNatalie.Li@Sun.COM 
758*10001SJoyce.McIntosh@Sun.COM 	if (buf_size < SVCCTL_ENUMSERVICES_MINBUFSIZE) {
7597961SNatalie.Li@Sun.COM 		param->bytes_needed = mgr_ctx->mc_bytes_needed;
7607961SNatalie.Li@Sun.COM 		param->svc_num = 0;
761*10001SJoyce.McIntosh@Sun.COM 		if (param->resume_handle)
762*10001SJoyce.McIntosh@Sun.COM 			*param->resume_handle = 0;
7637961SNatalie.Li@Sun.COM 		param->status = ERROR_MORE_DATA;
7648334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
7657961SNatalie.Li@Sun.COM 	}
7667961SNatalie.Li@Sun.COM 
767*10001SJoyce.McIntosh@Sun.COM 	svc_num = svcctl_scm_enum_services(mgr_ctx, param->services,
768*10001SJoyce.McIntosh@Sun.COM 	    buf_size, &resume_handle, B_TRUE);
769*10001SJoyce.McIntosh@Sun.COM 
770*10001SJoyce.McIntosh@Sun.COM 	param->buf_size = buf_size;
771*10001SJoyce.McIntosh@Sun.COM 	param->svc_num = svc_num;
7727961SNatalie.Li@Sun.COM 
773*10001SJoyce.McIntosh@Sun.COM 	if (resume_handle != 0) {
774*10001SJoyce.McIntosh@Sun.COM 		if (param->resume_handle != NULL)
775*10001SJoyce.McIntosh@Sun.COM 			*param->resume_handle = resume_handle;
776*10001SJoyce.McIntosh@Sun.COM 		param->bytes_needed = mgr_ctx->mc_bytes_needed;
777*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_MORE_DATA;
778*10001SJoyce.McIntosh@Sun.COM 	} else {
779*10001SJoyce.McIntosh@Sun.COM 		if (param->resume_handle)
780*10001SJoyce.McIntosh@Sun.COM 			*param->resume_handle = 0;
781*10001SJoyce.McIntosh@Sun.COM 		param->bytes_needed = 0;
782*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_SUCCESS;
783*10001SJoyce.McIntosh@Sun.COM 	}
784*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
785*10001SJoyce.McIntosh@Sun.COM 
786*10001SJoyce.McIntosh@Sun.COM enum_services_status_error:
787*10001SJoyce.McIntosh@Sun.COM 	bzero(param, sizeof (struct svcctl_EnumServicesStatus));
788*10001SJoyce.McIntosh@Sun.COM 	param->services = NDR_STRDUP(mxa, "");
789*10001SJoyce.McIntosh@Sun.COM 	param->status = status;
7908334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
7917961SNatalie.Li@Sun.COM }
7927961SNatalie.Li@Sun.COM 
7937961SNatalie.Li@Sun.COM /*
7947961SNatalie.Li@Sun.COM  * svcctl_s_QueryServiceConfig
7957961SNatalie.Li@Sun.COM  *
7967961SNatalie.Li@Sun.COM  * Returns:
7977961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
7987961SNatalie.Li@Sun.COM  *	ERROR_INVALID_HANDLE
7997961SNatalie.Li@Sun.COM  */
8007961SNatalie.Li@Sun.COM static int
8018334SJose.Borrego@Sun.COM svcctl_s_QueryServiceConfig(void *arg, ndr_xa_t *mxa)
8027961SNatalie.Li@Sun.COM {
8037961SNatalie.Li@Sun.COM 	struct svcctl_QueryServiceConfig *param = arg;
8047961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
8057961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
8067961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
8077961SNatalie.Li@Sun.COM 	svcctl_service_context_t *svc_ctx;
8087961SNatalie.Li@Sun.COM 	svcctl_svc_node_t *svc;
8097961SNatalie.Li@Sun.COM 	int bytes_needed = 0;
8107961SNatalie.Li@Sun.COM 	svc_config_t *cfg;
8117961SNatalie.Li@Sun.COM 
8127961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
8137961SNatalie.Li@Sun.COM 	if (hd == NULL) {
8147961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceConfig));
8157961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
8168334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8177961SNatalie.Li@Sun.COM 	}
8187961SNatalie.Li@Sun.COM 
8197961SNatalie.Li@Sun.COM 	svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc;
8207961SNatalie.Li@Sun.COM 	mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid);
8217961SNatalie.Li@Sun.COM 	if (mgr_ctx == NULL) {
8227961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceConfig));
8237961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
8248334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8257961SNatalie.Li@Sun.COM 	}
8267961SNatalie.Li@Sun.COM 
8277961SNatalie.Li@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname);
8287961SNatalie.Li@Sun.COM 	if (svc == NULL || svc->sn_fmri == NULL) {
8297961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceConfig));
8307961SNatalie.Li@Sun.COM 		param->status = ERROR_SERVICE_DOES_NOT_EXIST;
8318334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8327961SNatalie.Li@Sun.COM 	}
8337961SNatalie.Li@Sun.COM 
8347961SNatalie.Li@Sun.COM 	cfg = &param->service_cfg;
8357961SNatalie.Li@Sun.COM 	cfg->service_type = SERVICE_WIN32_SHARE_PROCESS;
8367961SNatalie.Li@Sun.COM 	cfg->start_type = SERVICE_AUTO_START;
8377961SNatalie.Li@Sun.COM 	cfg->error_control = SERVICE_AUTO_START;
8388334SJose.Borrego@Sun.COM 	cfg->binary_pathname = NDR_STRDUP(mxa, "");
8398334SJose.Borrego@Sun.COM 	cfg->loadorder_group = NDR_STRDUP(mxa, "");
8407961SNatalie.Li@Sun.COM 	cfg->tag_id = 0;
8418334SJose.Borrego@Sun.COM 	cfg->dependencies = NDR_STRDUP(mxa, "");
8428334SJose.Borrego@Sun.COM 	cfg->service_startname = NDR_STRDUP(mxa, "");
8438334SJose.Borrego@Sun.COM 	cfg->display_name = NDR_STRDUP(mxa, svc->sn_fmri);
8447961SNatalie.Li@Sun.COM 
8457961SNatalie.Li@Sun.COM 	bytes_needed = sizeof (svc_config_t);
8467961SNatalie.Li@Sun.COM 	bytes_needed += SVCCTL_WNSTRLEN((const char *)cfg->binary_pathname);
8477961SNatalie.Li@Sun.COM 	bytes_needed += SVCCTL_WNSTRLEN((const char *)cfg->loadorder_group);
8487961SNatalie.Li@Sun.COM 	bytes_needed += SVCCTL_WNSTRLEN((const char *)cfg->dependencies);
8497961SNatalie.Li@Sun.COM 	bytes_needed += SVCCTL_WNSTRLEN((const char *)cfg->service_startname);
8507961SNatalie.Li@Sun.COM 	bytes_needed += SVCCTL_WNSTRLEN(svc->sn_fmri);
8517961SNatalie.Li@Sun.COM 
8527961SNatalie.Li@Sun.COM 	if (param->buf_size < bytes_needed) {
8537961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceConfig));
8547961SNatalie.Li@Sun.COM 		param->cfg_bytes = bytes_needed;
855*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INSUFFICIENT_BUFFER;
8568334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8577961SNatalie.Li@Sun.COM 	}
8587961SNatalie.Li@Sun.COM 
8597961SNatalie.Li@Sun.COM 	param->cfg_bytes = bytes_needed;
8607961SNatalie.Li@Sun.COM 	param->status = ERROR_SUCCESS;
8618334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
8627961SNatalie.Li@Sun.COM }
8637961SNatalie.Li@Sun.COM 
8647961SNatalie.Li@Sun.COM /*
865*10001SJoyce.McIntosh@Sun.COM  * svcctl_s_StartService
866*10001SJoyce.McIntosh@Sun.COM  */
867*10001SJoyce.McIntosh@Sun.COM static int
868*10001SJoyce.McIntosh@Sun.COM svcctl_s_StartService(void *arg, ndr_xa_t *mxa)
869*10001SJoyce.McIntosh@Sun.COM {
870*10001SJoyce.McIntosh@Sun.COM 	struct svcctl_StartService *param = arg;
871*10001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
872*10001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
873*10001SJoyce.McIntosh@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
874*10001SJoyce.McIntosh@Sun.COM 	svcctl_service_context_t *svc_ctx;
875*10001SJoyce.McIntosh@Sun.COM 	svcctl_svc_node_t *svc;
876*10001SJoyce.McIntosh@Sun.COM 
877*10001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
878*10001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
879*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
880*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
881*10001SJoyce.McIntosh@Sun.COM 	}
882*10001SJoyce.McIntosh@Sun.COM 
883*10001SJoyce.McIntosh@Sun.COM 	svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc;
884*10001SJoyce.McIntosh@Sun.COM 	mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid);
885*10001SJoyce.McIntosh@Sun.COM 	if (mgr_ctx == NULL) {
886*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
887*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
888*10001SJoyce.McIntosh@Sun.COM 	}
889*10001SJoyce.McIntosh@Sun.COM 
890*10001SJoyce.McIntosh@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname);
891*10001SJoyce.McIntosh@Sun.COM 	if (svc == NULL || svc->sn_fmri == NULL)
892*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_SERVICE_DOES_NOT_EXIST;
893*10001SJoyce.McIntosh@Sun.COM 	else
894*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_SERVICE_ALREADY_RUNNING;
895*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
896*10001SJoyce.McIntosh@Sun.COM }
897*10001SJoyce.McIntosh@Sun.COM 
898*10001SJoyce.McIntosh@Sun.COM 
899*10001SJoyce.McIntosh@Sun.COM /*
9007961SNatalie.Li@Sun.COM  * svcctl_s_GetServiceDisplayNameW
9017961SNatalie.Li@Sun.COM  *
9027961SNatalie.Li@Sun.COM  * Returns:
9037961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
9047961SNatalie.Li@Sun.COM  *	ERROR_INVALID_HANDLE
9057961SNatalie.Li@Sun.COM  *	ERROR_SERVICE_DOES_NOT_EXIST
9067961SNatalie.Li@Sun.COM  */
9077961SNatalie.Li@Sun.COM static int
9088334SJose.Borrego@Sun.COM svcctl_s_GetServiceDisplayNameW(void *arg, ndr_xa_t *mxa)
9097961SNatalie.Li@Sun.COM {
9107961SNatalie.Li@Sun.COM 	struct svcctl_GetServiceDisplayNameW *param = arg;
9117961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->manager_handle;
9127961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
9137961SNatalie.Li@Sun.COM 	svcctl_svc_node_t *svc;
9147961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
9157961SNatalie.Li@Sun.COM 
9167961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_MANAGER_CONTEXT);
9177961SNatalie.Li@Sun.COM 	if (hd == NULL) {
9187961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_GetServiceDisplayNameW));
9198334SJose.Borrego@Sun.COM 		param->display_name = NDR_STRDUP(mxa, "");
9207961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
9218334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
9227961SNatalie.Li@Sun.COM 	}
9237961SNatalie.Li@Sun.COM 
9247961SNatalie.Li@Sun.COM 	mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr;
9257961SNatalie.Li@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, (char *)param->service_name);
9267961SNatalie.Li@Sun.COM 	if (svc == NULL || svc->sn_fmri == NULL) {
9277961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_GetServiceDisplayNameW));
9288334SJose.Borrego@Sun.COM 		param->display_name = NDR_STRDUP(mxa, "");
9297961SNatalie.Li@Sun.COM 		param->status = ERROR_SERVICE_DOES_NOT_EXIST;
9308334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
9317961SNatalie.Li@Sun.COM 	}
9327961SNatalie.Li@Sun.COM 
9338334SJose.Borrego@Sun.COM 	param->display_name = NDR_STRDUP(mxa, svc->sn_fmri);
9347961SNatalie.Li@Sun.COM 	if (param->display_name == NULL) {
9357961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_GetServiceDisplayNameW));
9368334SJose.Borrego@Sun.COM 		param->display_name = NDR_STRDUP(mxa, "");
9377961SNatalie.Li@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
9388334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
9397961SNatalie.Li@Sun.COM 	}
9407961SNatalie.Li@Sun.COM 
9417961SNatalie.Li@Sun.COM 	param->buf_size = strlen(svc->sn_fmri);
9427961SNatalie.Li@Sun.COM 	param->status = ERROR_SUCCESS;
9438334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
9447961SNatalie.Li@Sun.COM }
9457961SNatalie.Li@Sun.COM 
9467961SNatalie.Li@Sun.COM /*
9477961SNatalie.Li@Sun.COM  * svcctl_s_GetServiceKeyNameW
9487961SNatalie.Li@Sun.COM  *
9497961SNatalie.Li@Sun.COM  * Returns:
9507961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
9517961SNatalie.Li@Sun.COM  *	ERROR_INVALID_HANDLE
9527961SNatalie.Li@Sun.COM  *	ERROR_SERVICE_DOES_NOT_EXIST
9537961SNatalie.Li@Sun.COM  */
9547961SNatalie.Li@Sun.COM static int
9558334SJose.Borrego@Sun.COM svcctl_s_GetServiceKeyNameW(void *arg, ndr_xa_t *mxa)
9567961SNatalie.Li@Sun.COM {
9577961SNatalie.Li@Sun.COM 	struct svcctl_GetServiceKeyNameW *param = arg;
9587961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->manager_handle;
9597961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
9607961SNatalie.Li@Sun.COM 	svcctl_svc_node_t *svc;
9617961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
9627961SNatalie.Li@Sun.COM 
9637961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_MANAGER_CONTEXT);
9647961SNatalie.Li@Sun.COM 	if (hd == NULL) {
9657961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_GetServiceKeyNameW));
9668334SJose.Borrego@Sun.COM 		param->key_name = NDR_STRDUP(mxa, "");
9677961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
9688334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
9697961SNatalie.Li@Sun.COM 	}
9707961SNatalie.Li@Sun.COM 
9717961SNatalie.Li@Sun.COM 	mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr;
9727961SNatalie.Li@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, (char *)param->service_name);
9737961SNatalie.Li@Sun.COM 	if (svc == NULL || svc->sn_name == NULL) {
9747961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_GetServiceKeyNameW));
9758334SJose.Borrego@Sun.COM 		param->key_name = NDR_STRDUP(mxa, "");
9767961SNatalie.Li@Sun.COM 		param->status = ERROR_SERVICE_DOES_NOT_EXIST;
9778334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
9787961SNatalie.Li@Sun.COM 	}
9797961SNatalie.Li@Sun.COM 
9808334SJose.Borrego@Sun.COM 	param->key_name = NDR_STRDUP(mxa, svc->sn_name);
9817961SNatalie.Li@Sun.COM 	if (param->key_name == NULL) {
9827961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_GetServiceKeyNameW));
9838334SJose.Borrego@Sun.COM 		param->key_name = NDR_STRDUP(mxa, "");
9847961SNatalie.Li@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
9858334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
9867961SNatalie.Li@Sun.COM 	}
9877961SNatalie.Li@Sun.COM 
9887961SNatalie.Li@Sun.COM 	param->buf_size = strlen(svc->sn_name);
9897961SNatalie.Li@Sun.COM 	param->status = ERROR_SUCCESS;
9908334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
9917961SNatalie.Li@Sun.COM }
9927961SNatalie.Li@Sun.COM 
9937961SNatalie.Li@Sun.COM /*
994*10001SJoyce.McIntosh@Sun.COM  * svcctl_s_OpenSCManagerA
995*10001SJoyce.McIntosh@Sun.COM  *
996*10001SJoyce.McIntosh@Sun.COM  * Request to open the service control manager.
997*10001SJoyce.McIntosh@Sun.COM  * The caller must have administrator rights in order to open this
998*10001SJoyce.McIntosh@Sun.COM  * interface.  We don't support write (SC_MANAGER_LOCK) access.
999*10001SJoyce.McIntosh@Sun.COM  *
1000*10001SJoyce.McIntosh@Sun.COM  * Returns:
1001*10001SJoyce.McIntosh@Sun.COM  *	ERROR_SUCCESS
1002*10001SJoyce.McIntosh@Sun.COM  *	ERROR_ACCESS_DENIED
1003*10001SJoyce.McIntosh@Sun.COM  *
1004*10001SJoyce.McIntosh@Sun.COM  * On success, returns a handle for use with subsequent svcctl requests.
1005*10001SJoyce.McIntosh@Sun.COM  */
1006*10001SJoyce.McIntosh@Sun.COM static int
1007*10001SJoyce.McIntosh@Sun.COM svcctl_s_OpenSCManagerA(void *arg, ndr_xa_t *mxa)
1008*10001SJoyce.McIntosh@Sun.COM {
1009*10001SJoyce.McIntosh@Sun.COM 	struct svcctl_OpenSCManagerA *param = arg;
1010*10001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = NULL;
1011*10001SJoyce.McIntosh@Sun.COM 	int rc;
1012*10001SJoyce.McIntosh@Sun.COM 
1013*10001SJoyce.McIntosh@Sun.COM 	rc = ndr_is_admin(mxa);
1014*10001SJoyce.McIntosh@Sun.COM 
1015*10001SJoyce.McIntosh@Sun.COM 	if ((rc == 0) || (param->desired_access & SC_MANAGER_LOCK) != 0) {
1016*10001SJoyce.McIntosh@Sun.COM 		bzero(&param->handle, sizeof (svcctl_handle_t));
1017*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
1018*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
1019*10001SJoyce.McIntosh@Sun.COM 	}
1020*10001SJoyce.McIntosh@Sun.COM 
1021*10001SJoyce.McIntosh@Sun.COM 	id = svcctl_mgr_hdalloc(mxa);
1022*10001SJoyce.McIntosh@Sun.COM 	if (id) {
1023*10001SJoyce.McIntosh@Sun.COM 		bcopy(id, &param->handle, sizeof (svcctl_handle_t));
1024*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_SUCCESS;
1025*10001SJoyce.McIntosh@Sun.COM 	} else {
1026*10001SJoyce.McIntosh@Sun.COM 		bzero(&param->handle, sizeof (svcctl_handle_t));
1027*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
1028*10001SJoyce.McIntosh@Sun.COM 	}
1029*10001SJoyce.McIntosh@Sun.COM 
1030*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
1031*10001SJoyce.McIntosh@Sun.COM }
1032*10001SJoyce.McIntosh@Sun.COM 
1033*10001SJoyce.McIntosh@Sun.COM /*
1034*10001SJoyce.McIntosh@Sun.COM  * svcctl_s_OpenServiceA
1035*10001SJoyce.McIntosh@Sun.COM  *
1036*10001SJoyce.McIntosh@Sun.COM  * Return a handle for use with subsequent svcctl requests.
1037*10001SJoyce.McIntosh@Sun.COM  *
1038*10001SJoyce.McIntosh@Sun.COM  * Returns:
1039*10001SJoyce.McIntosh@Sun.COM  *	ERROR_SUCCESS
1040*10001SJoyce.McIntosh@Sun.COM  *	ERROR_INVALID_HANDLE
1041*10001SJoyce.McIntosh@Sun.COM  *	ERROR_SERVICE_DOES_NOT_EXIST
1042*10001SJoyce.McIntosh@Sun.COM  *	ERROR_CALL_NOT_IMPLEMENTED
1043*10001SJoyce.McIntosh@Sun.COM  */
1044*10001SJoyce.McIntosh@Sun.COM static int
1045*10001SJoyce.McIntosh@Sun.COM svcctl_s_OpenServiceA(void *arg, ndr_xa_t *mxa)
1046*10001SJoyce.McIntosh@Sun.COM {
1047*10001SJoyce.McIntosh@Sun.COM 	struct svcctl_OpenServiceA *param = arg;
1048*10001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *mgrid = (ndr_hdid_t *)&param->manager_handle;
1049*10001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = NULL;
1050*10001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
1051*10001SJoyce.McIntosh@Sun.COM 	DWORD status;
1052*10001SJoyce.McIntosh@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
1053*10001SJoyce.McIntosh@Sun.COM 	char *svc_name = (char *)param->service_name->value;
1054*10001SJoyce.McIntosh@Sun.COM 	boolean_t unimplemented_operations = B_FALSE;
1055*10001SJoyce.McIntosh@Sun.COM 
1056*10001SJoyce.McIntosh@Sun.COM 	/* Allow service handle allocations for only status & config queries */
1057*10001SJoyce.McIntosh@Sun.COM 	unimplemented_operations =
1058*10001SJoyce.McIntosh@Sun.COM 	    SVCCTL_OPENSVC_OP_UNIMPLEMENTED(param->desired_access);
1059*10001SJoyce.McIntosh@Sun.COM 
1060*10001SJoyce.McIntosh@Sun.COM 	if (unimplemented_operations) {
1061*10001SJoyce.McIntosh@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
1062*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_CALL_NOT_IMPLEMENTED;
1063*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
1064*10001SJoyce.McIntosh@Sun.COM 	}
1065*10001SJoyce.McIntosh@Sun.COM 
1066*10001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, mgrid, SVCCTL_MANAGER_CONTEXT);
1067*10001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
1068*10001SJoyce.McIntosh@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
1069*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
1070*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
1071*10001SJoyce.McIntosh@Sun.COM 	}
1072*10001SJoyce.McIntosh@Sun.COM 
1073*10001SJoyce.McIntosh@Sun.COM 	mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr;
1074*10001SJoyce.McIntosh@Sun.COM 	status = svcctl_scm_validate_service(mgr_ctx, svc_name);
1075*10001SJoyce.McIntosh@Sun.COM 	if (status != ERROR_SUCCESS) {
1076*10001SJoyce.McIntosh@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
1077*10001SJoyce.McIntosh@Sun.COM 		param->status = status;
1078*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
1079*10001SJoyce.McIntosh@Sun.COM 	}
1080*10001SJoyce.McIntosh@Sun.COM 
1081*10001SJoyce.McIntosh@Sun.COM 	id = svcctl_svc_hdalloc(mxa, mgrid, svc_name);
1082*10001SJoyce.McIntosh@Sun.COM 	if (id) {
1083*10001SJoyce.McIntosh@Sun.COM 		bcopy(id, &param->service_handle, sizeof (svcctl_handle_t));
1084*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_SUCCESS;
1085*10001SJoyce.McIntosh@Sun.COM 	} else {
1086*10001SJoyce.McIntosh@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
1087*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
1088*10001SJoyce.McIntosh@Sun.COM 	}
1089*10001SJoyce.McIntosh@Sun.COM 
1090*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
1091*10001SJoyce.McIntosh@Sun.COM }
1092*10001SJoyce.McIntosh@Sun.COM 
1093*10001SJoyce.McIntosh@Sun.COM /*
1094*10001SJoyce.McIntosh@Sun.COM  * svcctl_s_EnumServicesStatusA
1095*10001SJoyce.McIntosh@Sun.COM  *
1096*10001SJoyce.McIntosh@Sun.COM  * Enumerate the list of services we support as ASCII.
1097*10001SJoyce.McIntosh@Sun.COM  */
1098*10001SJoyce.McIntosh@Sun.COM static int
1099*10001SJoyce.McIntosh@Sun.COM svcctl_s_EnumServicesStatusA(void *arg, ndr_xa_t *mxa)
1100*10001SJoyce.McIntosh@Sun.COM {
1101*10001SJoyce.McIntosh@Sun.COM 	struct svcctl_EnumServicesStatusA *param = arg;
1102*10001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->manager_handle;
1103*10001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
1104*10001SJoyce.McIntosh@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
1105*10001SJoyce.McIntosh@Sun.COM 	uint32_t buf_size;
1106*10001SJoyce.McIntosh@Sun.COM 	uint32_t svc_num;
1107*10001SJoyce.McIntosh@Sun.COM 	uint32_t resume_handle = 0;
1108*10001SJoyce.McIntosh@Sun.COM 	uint32_t status;
1109*10001SJoyce.McIntosh@Sun.COM 
1110*10001SJoyce.McIntosh@Sun.COM 	buf_size = param->buf_size;
1111*10001SJoyce.McIntosh@Sun.COM 	if (param->resume_handle != NULL)
1112*10001SJoyce.McIntosh@Sun.COM 		resume_handle = *param->resume_handle;
1113*10001SJoyce.McIntosh@Sun.COM 
1114*10001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_MANAGER_CONTEXT);
1115*10001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
1116*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
1117*10001SJoyce.McIntosh@Sun.COM 		goto enum_services_status_error;
1118*10001SJoyce.McIntosh@Sun.COM 	}
1119*10001SJoyce.McIntosh@Sun.COM 
1120*10001SJoyce.McIntosh@Sun.COM 	mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr;
1121*10001SJoyce.McIntosh@Sun.COM 	if (svcctl_scm_refresh(mgr_ctx) != 0) {
1122*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
1123*10001SJoyce.McIntosh@Sun.COM 		goto enum_services_status_error;
1124*10001SJoyce.McIntosh@Sun.COM 	}
1125*10001SJoyce.McIntosh@Sun.COM 
1126*10001SJoyce.McIntosh@Sun.COM 	param->services = NDR_MALLOC(mxa, buf_size);
1127*10001SJoyce.McIntosh@Sun.COM 	if (param->services == NULL) {
1128*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
1129*10001SJoyce.McIntosh@Sun.COM 		goto enum_services_status_error;
1130*10001SJoyce.McIntosh@Sun.COM 	}
1131*10001SJoyce.McIntosh@Sun.COM 	bzero(param->services, buf_size);
1132*10001SJoyce.McIntosh@Sun.COM 
1133*10001SJoyce.McIntosh@Sun.COM 	svc_num = svcctl_scm_enum_services(mgr_ctx, param->services,
1134*10001SJoyce.McIntosh@Sun.COM 	    buf_size, &resume_handle, B_FALSE);
1135*10001SJoyce.McIntosh@Sun.COM 
1136*10001SJoyce.McIntosh@Sun.COM 	param->buf_size = buf_size;
1137*10001SJoyce.McIntosh@Sun.COM 	param->svc_num = svc_num;
1138*10001SJoyce.McIntosh@Sun.COM 
1139*10001SJoyce.McIntosh@Sun.COM 	if (resume_handle != 0) {
1140*10001SJoyce.McIntosh@Sun.COM 		if (param->resume_handle != NULL)
1141*10001SJoyce.McIntosh@Sun.COM 			*param->resume_handle = resume_handle;
1142*10001SJoyce.McIntosh@Sun.COM 		param->bytes_needed = mgr_ctx->mc_bytes_needed;
1143*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_MORE_DATA;
1144*10001SJoyce.McIntosh@Sun.COM 	} else {
1145*10001SJoyce.McIntosh@Sun.COM 		if (param->resume_handle)
1146*10001SJoyce.McIntosh@Sun.COM 			*param->resume_handle = 0;
1147*10001SJoyce.McIntosh@Sun.COM 		param->bytes_needed = 0;
1148*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_SUCCESS;
1149*10001SJoyce.McIntosh@Sun.COM 	}
1150*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
1151*10001SJoyce.McIntosh@Sun.COM 
1152*10001SJoyce.McIntosh@Sun.COM enum_services_status_error:
1153*10001SJoyce.McIntosh@Sun.COM 	bzero(param, sizeof (struct svcctl_EnumServicesStatusA));
1154*10001SJoyce.McIntosh@Sun.COM 	param->services = NDR_STRDUP(mxa, "");
1155*10001SJoyce.McIntosh@Sun.COM 	param->status = status;
1156*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
1157*10001SJoyce.McIntosh@Sun.COM }
1158*10001SJoyce.McIntosh@Sun.COM 
1159*10001SJoyce.McIntosh@Sun.COM /*
11607961SNatalie.Li@Sun.COM  * svcctl_s_QueryServiceConfig2W
11617961SNatalie.Li@Sun.COM  *
11627961SNatalie.Li@Sun.COM  * Returns:
11637961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
11647961SNatalie.Li@Sun.COM  *	ERROR_INVALID_HANDLE
11657961SNatalie.Li@Sun.COM  *	ERROR_INVALID_LEVEL
11667961SNatalie.Li@Sun.COM  *	ERROR_NOT_ENOUGH_MEMORY
11677961SNatalie.Li@Sun.COM  */
11687961SNatalie.Li@Sun.COM static int
11698334SJose.Borrego@Sun.COM svcctl_s_QueryServiceConfig2W(void *arg, ndr_xa_t *mxa)
11707961SNatalie.Li@Sun.COM {
11717961SNatalie.Li@Sun.COM 	struct svcctl_QueryServiceConfig2W *param = arg;
11727961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
11737961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
11747961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
11757961SNatalie.Li@Sun.COM 	svcctl_service_context_t *svc_ctx;
11767961SNatalie.Li@Sun.COM 	svcctl_svc_node_t *svc;
11777961SNatalie.Li@Sun.COM 	svc_description_t *svc_desc;
11787961SNatalie.Li@Sun.COM 	svc_failure_actions_t *fac;
11797961SNatalie.Li@Sun.COM 	int offset, input_bufsize, bytes_needed = 0;
11807961SNatalie.Li@Sun.COM 	mts_wchar_t *wide_desc;
11817961SNatalie.Li@Sun.COM 	char *desc;
11827961SNatalie.Li@Sun.COM 	DWORD status;
11837961SNatalie.Li@Sun.COM 
11847961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
11857961SNatalie.Li@Sun.COM 	if (hd == NULL) {
11867961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceConfig2W));
11878334SJose.Borrego@Sun.COM 		param->buffer = NDR_STRDUP(mxa, "");
11887961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
11898334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
11907961SNatalie.Li@Sun.COM 	}
11917961SNatalie.Li@Sun.COM 
11927961SNatalie.Li@Sun.COM 	input_bufsize = param->buf_size;
11938334SJose.Borrego@Sun.COM 	param->buffer = NDR_MALLOC(mxa, input_bufsize);
11947961SNatalie.Li@Sun.COM 	if (param->buffer == NULL) {
11957961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceConfig2W));
11968334SJose.Borrego@Sun.COM 		param->buffer = NDR_STRDUP(mxa, "");
11977961SNatalie.Li@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
11988334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
11997961SNatalie.Li@Sun.COM 	}
12007961SNatalie.Li@Sun.COM 	bzero(param->buffer, input_bufsize);
12017961SNatalie.Li@Sun.COM 
12027961SNatalie.Li@Sun.COM 	status = ERROR_SUCCESS;
12037961SNatalie.Li@Sun.COM 	switch (param->info_level) {
12047961SNatalie.Li@Sun.COM 	case SERVICE_CONFIG_DESCRIPTION:
12057961SNatalie.Li@Sun.COM 		svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc;
12067961SNatalie.Li@Sun.COM 		mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid);
12077961SNatalie.Li@Sun.COM 		if (mgr_ctx == NULL) {
12087961SNatalie.Li@Sun.COM 			param->status = ERROR_INVALID_HANDLE;
12097961SNatalie.Li@Sun.COM 			break;
12107961SNatalie.Li@Sun.COM 		}
12117961SNatalie.Li@Sun.COM 
12127961SNatalie.Li@Sun.COM 		svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname);
12137961SNatalie.Li@Sun.COM 		if (svc == NULL || svc->sn_desc == NULL) {
12147961SNatalie.Li@Sun.COM 			status = ERROR_SERVICE_DOES_NOT_EXIST;
12157961SNatalie.Li@Sun.COM 			break;
12167961SNatalie.Li@Sun.COM 		}
12177961SNatalie.Li@Sun.COM 
12187961SNatalie.Li@Sun.COM 		desc = svc->sn_desc;
12197961SNatalie.Li@Sun.COM 		bytes_needed = SVCCTL_WNSTRLEN(desc);
12207961SNatalie.Li@Sun.COM 
12217961SNatalie.Li@Sun.COM 		if (input_bufsize <= bytes_needed) {
12227961SNatalie.Li@Sun.COM 			param->bytes_needed = bytes_needed;
1223*10001SJoyce.McIntosh@Sun.COM 			param->status = ERROR_INSUFFICIENT_BUFFER;
12248334SJose.Borrego@Sun.COM 			return (NDR_DRC_OK);
12257961SNatalie.Li@Sun.COM 		}
12267961SNatalie.Li@Sun.COM 
12277961SNatalie.Li@Sun.COM 		offset = sizeof (svc_description_t);
12287961SNatalie.Li@Sun.COM 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
12297961SNatalie.Li@Sun.COM 		svc_desc = (svc_description_t *)param->buffer;
12307961SNatalie.Li@Sun.COM 		svc_desc->desc = offset;
12317961SNatalie.Li@Sun.COM 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
12327961SNatalie.Li@Sun.COM 		wide_desc = (mts_wchar_t *)&param->buffer[offset];
12337961SNatalie.Li@Sun.COM 		(void) mts_mbstowcs(wide_desc, desc, (strlen(desc) + 1));
12347961SNatalie.Li@Sun.COM 		offset = SVCCTL_WNSTRLEN(desc);
12357961SNatalie.Li@Sun.COM 
12367961SNatalie.Li@Sun.COM 		param->bytes_needed = offset;
12377961SNatalie.Li@Sun.COM 		break;
12387961SNatalie.Li@Sun.COM 
12397961SNatalie.Li@Sun.COM 	case SERVICE_CONFIG_FAILURE_ACTIONS:
12407961SNatalie.Li@Sun.COM 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
12417961SNatalie.Li@Sun.COM 		fac = (svc_failure_actions_t *)param->buffer;
12427961SNatalie.Li@Sun.COM 		bzero(fac, sizeof (svc_failure_actions_t));
12437961SNatalie.Li@Sun.COM 
12447961SNatalie.Li@Sun.COM 		param->bytes_needed = input_bufsize;
12457961SNatalie.Li@Sun.COM 		break;
12467961SNatalie.Li@Sun.COM 
12477961SNatalie.Li@Sun.COM 	default:
12487961SNatalie.Li@Sun.COM 		status = ERROR_INVALID_LEVEL;
12497961SNatalie.Li@Sun.COM 		break;
12507961SNatalie.Li@Sun.COM 	}
12517961SNatalie.Li@Sun.COM 
12527961SNatalie.Li@Sun.COM 	if (status != ERROR_SUCCESS) {
12537961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceConfig2W));
12548334SJose.Borrego@Sun.COM 		param->buffer = NDR_STRDUP(mxa, "");
12557961SNatalie.Li@Sun.COM 		param->status = status;
12568334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
12577961SNatalie.Li@Sun.COM 	}
12587961SNatalie.Li@Sun.COM 
12597961SNatalie.Li@Sun.COM 	param->status = ERROR_SUCCESS;
12608334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
12617961SNatalie.Li@Sun.COM }
1262*10001SJoyce.McIntosh@Sun.COM 
1263*10001SJoyce.McIntosh@Sun.COM /*
1264*10001SJoyce.McIntosh@Sun.COM  * svcctl_s_QueryServiceStatusEx
1265*10001SJoyce.McIntosh@Sun.COM  */
1266*10001SJoyce.McIntosh@Sun.COM static int
1267*10001SJoyce.McIntosh@Sun.COM svcctl_s_QueryServiceStatusEx(void *arg, ndr_xa_t *mxa)
1268*10001SJoyce.McIntosh@Sun.COM {
1269*10001SJoyce.McIntosh@Sun.COM 	struct svcctl_QueryServiceStatusEx *param = arg;
1270*10001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
1271*10001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
1272*10001SJoyce.McIntosh@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
1273*10001SJoyce.McIntosh@Sun.COM 	svcctl_service_context_t *svc_ctx;
1274*10001SJoyce.McIntosh@Sun.COM 	svcctl_svc_node_t *svc;
1275*10001SJoyce.McIntosh@Sun.COM 	svc_status_ex_t *svc_status_ex;
1276*10001SJoyce.McIntosh@Sun.COM 	uint32_t input_bufsize;
1277*10001SJoyce.McIntosh@Sun.COM 	uint32_t bytes_needed;
1278*10001SJoyce.McIntosh@Sun.COM 	DWORD status;
1279*10001SJoyce.McIntosh@Sun.COM 
1280*10001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
1281*10001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
1282*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
1283*10001SJoyce.McIntosh@Sun.COM 		goto query_service_status_ex_error;
1284*10001SJoyce.McIntosh@Sun.COM 	}
1285*10001SJoyce.McIntosh@Sun.COM 
1286*10001SJoyce.McIntosh@Sun.COM 	svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc;
1287*10001SJoyce.McIntosh@Sun.COM 	mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid);
1288*10001SJoyce.McIntosh@Sun.COM 	if (mgr_ctx == NULL) {
1289*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
1290*10001SJoyce.McIntosh@Sun.COM 		goto query_service_status_ex_error;
1291*10001SJoyce.McIntosh@Sun.COM 	}
1292*10001SJoyce.McIntosh@Sun.COM 
1293*10001SJoyce.McIntosh@Sun.COM 	if (param->info_level != SC_STATUS_PROCESS_INFO) {
1294*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_PARAMETER;
1295*10001SJoyce.McIntosh@Sun.COM 		goto query_service_status_ex_error;
1296*10001SJoyce.McIntosh@Sun.COM 	}
1297*10001SJoyce.McIntosh@Sun.COM 
1298*10001SJoyce.McIntosh@Sun.COM 	bytes_needed = sizeof (struct svcctl_QueryServiceStatusEx);
1299*10001SJoyce.McIntosh@Sun.COM 
1300*10001SJoyce.McIntosh@Sun.COM 	if ((input_bufsize = param->buf_size) < bytes_needed) {
1301*10001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceStatusEx));
1302*10001SJoyce.McIntosh@Sun.COM 		param->buf_size = input_bufsize;
1303*10001SJoyce.McIntosh@Sun.COM 		param->buffer = NDR_STRDUP(mxa, "");
1304*10001SJoyce.McIntosh@Sun.COM 		param->bytes_needed = bytes_needed;
1305*10001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INSUFFICIENT_BUFFER;
1306*10001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
1307*10001SJoyce.McIntosh@Sun.COM 	}
1308*10001SJoyce.McIntosh@Sun.COM 
1309*10001SJoyce.McIntosh@Sun.COM 	if ((svc_status_ex = NDR_MALLOC(mxa, bytes_needed)) == NULL) {
1310*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
1311*10001SJoyce.McIntosh@Sun.COM 		goto query_service_status_ex_error;
1312*10001SJoyce.McIntosh@Sun.COM 	}
1313*10001SJoyce.McIntosh@Sun.COM 
1314*10001SJoyce.McIntosh@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname);
1315*10001SJoyce.McIntosh@Sun.COM 	if (svc == NULL || svc->sn_state == NULL) {
1316*10001SJoyce.McIntosh@Sun.COM 		status = ERROR_SERVICE_DOES_NOT_EXIST;
1317*10001SJoyce.McIntosh@Sun.COM 		goto query_service_status_ex_error;
1318*10001SJoyce.McIntosh@Sun.COM 	}
1319*10001SJoyce.McIntosh@Sun.COM 
1320*10001SJoyce.McIntosh@Sun.COM 	svc_status_ex->service_type = SERVICE_WIN32_SHARE_PROCESS;
1321*10001SJoyce.McIntosh@Sun.COM 	svc_status_ex->cur_state = svcctl_scm_map_status(svc->sn_state);
1322*10001SJoyce.McIntosh@Sun.COM 	svc_status_ex->ctrl_accepted = 0;
1323*10001SJoyce.McIntosh@Sun.COM 	svc_status_ex->w32_exitcode = 0;
1324*10001SJoyce.McIntosh@Sun.COM 	svc_status_ex->svc_specified_exitcode = 0;
1325*10001SJoyce.McIntosh@Sun.COM 	svc_status_ex->check_point = 0;
1326*10001SJoyce.McIntosh@Sun.COM 	svc_status_ex->wait_hint = 0;
1327*10001SJoyce.McIntosh@Sun.COM 	svc_status_ex->process_id = 1;
1328*10001SJoyce.McIntosh@Sun.COM 	svc_status_ex->service_flags = 1;
1329*10001SJoyce.McIntosh@Sun.COM 
1330*10001SJoyce.McIntosh@Sun.COM 	param->buffer = (uint8_t *)svc_status_ex;
1331*10001SJoyce.McIntosh@Sun.COM 	param->buf_size = bytes_needed;
1332*10001SJoyce.McIntosh@Sun.COM 	param->bytes_needed = 0;
1333*10001SJoyce.McIntosh@Sun.COM 	param->status = ERROR_SUCCESS;
1334*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
1335*10001SJoyce.McIntosh@Sun.COM 
1336*10001SJoyce.McIntosh@Sun.COM query_service_status_ex_error:
1337*10001SJoyce.McIntosh@Sun.COM 	bzero(param, sizeof (struct svcctl_QueryServiceStatusEx));
1338*10001SJoyce.McIntosh@Sun.COM 	param->buffer = NDR_STRDUP(mxa, "");
1339*10001SJoyce.McIntosh@Sun.COM 	param->status = status;
1340*10001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
1341*10001SJoyce.McIntosh@Sun.COM }
1342