xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/svcctl_svc.c (revision 10966:37e5dcdf36d3)
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 /*
2210001SJoyce.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>
3910001SJoyce.McIntosh@Sun.COM #include <smbsrv/ntifs.h>
4010122SJordan.Brown@Sun.COM #include <smbsrv/winsvc.h>
4110122SJordan.Brown@Sun.COM #include <smbsrv/nterror.h>
4210122SJordan.Brown@Sun.COM #include <smbsrv/ndl/svcctl.ndl>
4310122SJordan.Brown@Sun.COM #include <smbsrv/libmlsvc.h>
447961SNatalie.Li@Sun.COM 
4510001SJoyce.McIntosh@Sun.COM #define	SVCCTL_SECURITY_BUFSIZE		256
4610001SJoyce.McIntosh@Sun.COM #define	SVCCTL_ENUMSERVICES_MINBUFSIZE	1024
4710001SJoyce.McIntosh@Sun.COM 
487961SNatalie.Li@Sun.COM #define	SVCCTL_OPENSVC_OP_UNIMPLEMENTED(S)	\
497961SNatalie.Li@Sun.COM 	((S) & SERVICE_CHANGE_CONFIG)	||	\
507961SNatalie.Li@Sun.COM 	((S) & SERVICE_PAUSE_CONTINUE)	||	\
517961SNatalie.Li@Sun.COM 	((S) & SERVICE_START)		||	\
527961SNatalie.Li@Sun.COM 	((S) & SERVICE_STOP)		||	\
537961SNatalie.Li@Sun.COM 	((S) & SERVICE_ENUMERATE_DEPENDENTS)
547961SNatalie.Li@Sun.COM 
5510504SKeyur.Desai@Sun.COM typedef union {
5610504SKeyur.Desai@Sun.COM 	uint8_t				*svc_buf;
5710504SKeyur.Desai@Sun.COM 	svc_description_t		*svc_desc;
5810504SKeyur.Desai@Sun.COM 	svc_failure_actions_t		*svc_fac;
5910504SKeyur.Desai@Sun.COM 	svc_delayed_auto_start_t	*svc_dstart;
6010504SKeyur.Desai@Sun.COM 	svc_config_failure_action_t	*svc_cfa;
6110504SKeyur.Desai@Sun.COM } svc_config_rsp_t;
6210504SKeyur.Desai@Sun.COM 
638334SJose.Borrego@Sun.COM static int svcctl_s_Close(void *, ndr_xa_t *);
6410001SJoyce.McIntosh@Sun.COM static int svcctl_s_ControlService(void *, ndr_xa_t *);
6510001SJoyce.McIntosh@Sun.COM static int svcctl_s_DeleteService(void *, ndr_xa_t *);
6610001SJoyce.McIntosh@Sun.COM static int svcctl_s_QueryServiceSecurity(void *, ndr_xa_t *);
6710001SJoyce.McIntosh@Sun.COM static int svcctl_s_SetServiceSecurity(void *, ndr_xa_t *);
688334SJose.Borrego@Sun.COM static int svcctl_s_OpenManager(void *, ndr_xa_t *);
698334SJose.Borrego@Sun.COM static int svcctl_s_OpenService(void *, ndr_xa_t *);
708334SJose.Borrego@Sun.COM static int svcctl_s_QueryServiceStatus(void *, ndr_xa_t *);
718334SJose.Borrego@Sun.COM static int svcctl_s_QueryServiceConfig(void *, ndr_xa_t *);
7210001SJoyce.McIntosh@Sun.COM static int svcctl_s_StartService(void *, ndr_xa_t *);
7310001SJoyce.McIntosh@Sun.COM static int svcctl_s_EnumDependentServices(void *, ndr_xa_t *);
748334SJose.Borrego@Sun.COM static int svcctl_s_EnumServicesStatus(void *, ndr_xa_t *);
758334SJose.Borrego@Sun.COM static int svcctl_s_GetServiceDisplayNameW(void *, ndr_xa_t *);
768334SJose.Borrego@Sun.COM static int svcctl_s_GetServiceKeyNameW(void *, ndr_xa_t *);
7710001SJoyce.McIntosh@Sun.COM static int svcctl_s_OpenSCManagerA(void *, ndr_xa_t *);
7810001SJoyce.McIntosh@Sun.COM static int svcctl_s_OpenServiceA(void *, ndr_xa_t *);
7910001SJoyce.McIntosh@Sun.COM static int svcctl_s_EnumServicesStatusA(void *, ndr_xa_t *);
808334SJose.Borrego@Sun.COM static int svcctl_s_QueryServiceConfig2W(void *, ndr_xa_t *);
8110001SJoyce.McIntosh@Sun.COM static int svcctl_s_QueryServiceStatusEx(void *, ndr_xa_t *);
827961SNatalie.Li@Sun.COM 
838334SJose.Borrego@Sun.COM static ndr_stub_table_t svcctl_stub_table[] = {
847961SNatalie.Li@Sun.COM 	{ svcctl_s_Close,		SVCCTL_OPNUM_Close },
8510001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_ControlService,	SVCCTL_OPNUM_ControlService },
8610001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_DeleteService,	SVCCTL_OPNUM_DeleteService },
8710001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_QueryServiceSecurity, SVCCTL_OPNUM_QueryServiceSecurity },
8810001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_SetServiceSecurity,	SVCCTL_OPNUM_SetServiceSecurity },
897961SNatalie.Li@Sun.COM 	{ svcctl_s_OpenManager,		SVCCTL_OPNUM_OpenManager },
907961SNatalie.Li@Sun.COM 	{ svcctl_s_OpenService,		SVCCTL_OPNUM_OpenService },
917961SNatalie.Li@Sun.COM 	{ svcctl_s_QueryServiceStatus,	SVCCTL_OPNUM_QueryServiceStatus },
927961SNatalie.Li@Sun.COM 	{ svcctl_s_QueryServiceConfig,	SVCCTL_OPNUM_QueryServiceConfig },
9310001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_StartService,	SVCCTL_OPNUM_StartService },
9410001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_EnumDependentServices,
9510001SJoyce.McIntosh@Sun.COM 		SVCCTL_OPNUM_EnumDependentServices },
967961SNatalie.Li@Sun.COM 	{ svcctl_s_EnumServicesStatus,	SVCCTL_OPNUM_EnumServicesStatus },
977961SNatalie.Li@Sun.COM 	{ svcctl_s_GetServiceDisplayNameW,
987961SNatalie.Li@Sun.COM 		SVCCTL_OPNUM_GetServiceDisplayNameW },
997961SNatalie.Li@Sun.COM 	{ svcctl_s_GetServiceKeyNameW,	SVCCTL_OPNUM_GetServiceKeyNameW },
10010001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_OpenSCManagerA,	SVCCTL_OPNUM_OpenSCManagerA },
10110001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_OpenServiceA,	SVCCTL_OPNUM_OpenServiceA },
10210001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_EnumServicesStatusA,	SVCCTL_OPNUM_EnumServicesStatusA },
1037961SNatalie.Li@Sun.COM 	{ svcctl_s_QueryServiceConfig2W, SVCCTL_OPNUM_QueryServiceConfig2W },
10410001SJoyce.McIntosh@Sun.COM 	{ svcctl_s_QueryServiceStatusEx, SVCCTL_OPNUM_QueryServiceStatusEx },
1057961SNatalie.Li@Sun.COM 	{0}
1067961SNatalie.Li@Sun.COM };
1077961SNatalie.Li@Sun.COM 
1088334SJose.Borrego@Sun.COM static ndr_service_t svcctl_service = {
1097961SNatalie.Li@Sun.COM 	"SVCCTL",			/* name */
1107961SNatalie.Li@Sun.COM 	"Service Control Services",	/* desc */
1117961SNatalie.Li@Sun.COM 	"\\svcctl",			/* endpoint */
1127961SNatalie.Li@Sun.COM 	PIPE_NTSVCS,			/* sec_addr_port */
1138334SJose.Borrego@Sun.COM 	"367abb81-9844-35f1-ad32-98f038001003", 2,	/* abstract */
1148334SJose.Borrego@Sun.COM 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
1157961SNatalie.Li@Sun.COM 	0,				/* no bind_instance_size */
1167961SNatalie.Li@Sun.COM 	0,				/* no bind_req() */
1177961SNatalie.Li@Sun.COM 	0,				/* no unbind_and_close() */
1187961SNatalie.Li@Sun.COM 	0,				/* use generic_call_stub() */
1197961SNatalie.Li@Sun.COM 	&TYPEINFO(svcctl_interface),	/* interface ti */
1207961SNatalie.Li@Sun.COM 	svcctl_stub_table		/* stub_table */
1217961SNatalie.Li@Sun.COM };
1227961SNatalie.Li@Sun.COM 
1237961SNatalie.Li@Sun.COM /*
1247961SNatalie.Li@Sun.COM  * svcctl_initialize
1257961SNatalie.Li@Sun.COM  *
1267961SNatalie.Li@Sun.COM  * This function registers the SVCCTL RPC interface with the RPC runtime
1277961SNatalie.Li@Sun.COM  * library. It must be called in order to use either the client side
1287961SNatalie.Li@Sun.COM  * or the server side functions.
1297961SNatalie.Li@Sun.COM  */
1307961SNatalie.Li@Sun.COM void
1317961SNatalie.Li@Sun.COM svcctl_initialize(void)
1327961SNatalie.Li@Sun.COM {
1338334SJose.Borrego@Sun.COM 	(void) ndr_svc_register(&svcctl_service);
13410122SJordan.Brown@Sun.COM 	svcctl_init();
13510122SJordan.Brown@Sun.COM }
13610122SJordan.Brown@Sun.COM 
13710122SJordan.Brown@Sun.COM void
13810122SJordan.Brown@Sun.COM svcctl_finalize(void)
13910122SJordan.Brown@Sun.COM {
14010122SJordan.Brown@Sun.COM 	svcctl_fini();
1417961SNatalie.Li@Sun.COM }
1427961SNatalie.Li@Sun.COM 
1437961SNatalie.Li@Sun.COM /*
1447961SNatalie.Li@Sun.COM  * svcctl_hdlookup
1457961SNatalie.Li@Sun.COM  *
1467961SNatalie.Li@Sun.COM  * Handle lookup wrapper to validate the local service and/or manager context.
1477961SNatalie.Li@Sun.COM  */
1487961SNatalie.Li@Sun.COM static ndr_handle_t *
1497961SNatalie.Li@Sun.COM svcctl_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, svcctl_context_type_t type)
1507961SNatalie.Li@Sun.COM {
1517961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
1527961SNatalie.Li@Sun.COM 	svcctl_context_t *ctx;
1537961SNatalie.Li@Sun.COM 
1547961SNatalie.Li@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) == NULL)
1557961SNatalie.Li@Sun.COM 		return (NULL);
1567961SNatalie.Li@Sun.COM 
1577961SNatalie.Li@Sun.COM 	if ((ctx = (svcctl_context_t *)hd->nh_data) == NULL)
1587961SNatalie.Li@Sun.COM 		return (NULL);
1597961SNatalie.Li@Sun.COM 
1607961SNatalie.Li@Sun.COM 	if ((ctx->c_type != type) || (ctx->c_ctx.uc_cp == NULL))
1617961SNatalie.Li@Sun.COM 		return (NULL);
1627961SNatalie.Li@Sun.COM 
1637961SNatalie.Li@Sun.COM 	return (hd);
1647961SNatalie.Li@Sun.COM }
1657961SNatalie.Li@Sun.COM 
1667961SNatalie.Li@Sun.COM /*
1677961SNatalie.Li@Sun.COM  * svcctl_hdfree
1687961SNatalie.Li@Sun.COM  *
1697961SNatalie.Li@Sun.COM  * Handle deallocation wrapper to free the local service and/or manager context.
1707961SNatalie.Li@Sun.COM  */
1717961SNatalie.Li@Sun.COM static void
1727961SNatalie.Li@Sun.COM svcctl_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id)
1737961SNatalie.Li@Sun.COM {
1747961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
1757961SNatalie.Li@Sun.COM 	svcctl_context_t *ctx;
1767961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
1777961SNatalie.Li@Sun.COM 	svcctl_service_context_t *svc_ctx;
1787961SNatalie.Li@Sun.COM 
1797961SNatalie.Li@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
1807961SNatalie.Li@Sun.COM 		ctx = (svcctl_context_t *)hd->nh_data;
1817961SNatalie.Li@Sun.COM 
1827961SNatalie.Li@Sun.COM 		switch (ctx->c_type) {
1837961SNatalie.Li@Sun.COM 		case SVCCTL_MANAGER_CONTEXT:
1847961SNatalie.Li@Sun.COM 			mgr_ctx = ctx->c_ctx.uc_mgr;
1857961SNatalie.Li@Sun.COM 			svcctl_scm_fini(mgr_ctx);
1867961SNatalie.Li@Sun.COM 			svcctl_scm_scf_handle_fini(mgr_ctx);
1877961SNatalie.Li@Sun.COM 			free(mgr_ctx);
1887961SNatalie.Li@Sun.COM 			break;
1897961SNatalie.Li@Sun.COM 
1907961SNatalie.Li@Sun.COM 		case SVCCTL_SERVICE_CONTEXT:
1917961SNatalie.Li@Sun.COM 			svc_ctx = ctx->c_ctx.uc_svc;
1927961SNatalie.Li@Sun.COM 			free(svc_ctx->sc_mgrid);
1937961SNatalie.Li@Sun.COM 			free(svc_ctx->sc_svcname);
1947961SNatalie.Li@Sun.COM 			free(svc_ctx);
1957961SNatalie.Li@Sun.COM 			break;
1967961SNatalie.Li@Sun.COM 
1977961SNatalie.Li@Sun.COM 		default:
1987961SNatalie.Li@Sun.COM 			break;
1997961SNatalie.Li@Sun.COM 		}
2007961SNatalie.Li@Sun.COM 
2017961SNatalie.Li@Sun.COM 		free(ctx);
2027961SNatalie.Li@Sun.COM 		ndr_hdfree(mxa, id);
2037961SNatalie.Li@Sun.COM 	}
2047961SNatalie.Li@Sun.COM }
2057961SNatalie.Li@Sun.COM 
2067961SNatalie.Li@Sun.COM /*
2077961SNatalie.Li@Sun.COM  * svcctl_mgr_hdalloc
2087961SNatalie.Li@Sun.COM  *
2097961SNatalie.Li@Sun.COM  * Handle allocation wrapper to setup the local manager context.
2107961SNatalie.Li@Sun.COM  */
2117961SNatalie.Li@Sun.COM static ndr_hdid_t *
2127961SNatalie.Li@Sun.COM svcctl_mgr_hdalloc(ndr_xa_t *mxa)
2137961SNatalie.Li@Sun.COM {
2147961SNatalie.Li@Sun.COM 	svcctl_context_t *ctx;
2157961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
2167961SNatalie.Li@Sun.COM 
2177961SNatalie.Li@Sun.COM 	if ((ctx = malloc(sizeof (svcctl_context_t))) == NULL)
2187961SNatalie.Li@Sun.COM 		return (NULL);
2197961SNatalie.Li@Sun.COM 	ctx->c_type = SVCCTL_MANAGER_CONTEXT;
2207961SNatalie.Li@Sun.COM 
2217961SNatalie.Li@Sun.COM 	if ((mgr_ctx = malloc(sizeof (svcctl_manager_context_t))) == NULL) {
2227961SNatalie.Li@Sun.COM 		free(ctx);
2237961SNatalie.Li@Sun.COM 		return (NULL);
2247961SNatalie.Li@Sun.COM 	}
2257961SNatalie.Li@Sun.COM 	bzero(mgr_ctx, sizeof (svcctl_manager_context_t));
2267961SNatalie.Li@Sun.COM 
2277961SNatalie.Li@Sun.COM 	if (svcctl_scm_scf_handle_init(mgr_ctx) < 0) {
2287961SNatalie.Li@Sun.COM 		free(mgr_ctx);
2297961SNatalie.Li@Sun.COM 		free(ctx);
2307961SNatalie.Li@Sun.COM 		return (NULL);
2317961SNatalie.Li@Sun.COM 	}
2327961SNatalie.Li@Sun.COM 
2337961SNatalie.Li@Sun.COM 	if (svcctl_scm_init(mgr_ctx) < 0) {
2347961SNatalie.Li@Sun.COM 		svcctl_scm_scf_handle_fini(mgr_ctx);
2357961SNatalie.Li@Sun.COM 		free(mgr_ctx);
2367961SNatalie.Li@Sun.COM 		free(ctx);
2377961SNatalie.Li@Sun.COM 		return (NULL);
2387961SNatalie.Li@Sun.COM 	}
2397961SNatalie.Li@Sun.COM 
2407961SNatalie.Li@Sun.COM 	ctx->c_ctx.uc_mgr = mgr_ctx;
2417961SNatalie.Li@Sun.COM 
2427961SNatalie.Li@Sun.COM 	return (ndr_hdalloc(mxa, ctx));
2437961SNatalie.Li@Sun.COM }
2447961SNatalie.Li@Sun.COM 
2457961SNatalie.Li@Sun.COM /*
2467961SNatalie.Li@Sun.COM  * svcctl_get_mgr_ctx
2477961SNatalie.Li@Sun.COM  *
2487961SNatalie.Li@Sun.COM  * This function looks up a reference to local manager context.
2497961SNatalie.Li@Sun.COM  */
2507961SNatalie.Li@Sun.COM static svcctl_manager_context_t *
2517961SNatalie.Li@Sun.COM svcctl_get_mgr_ctx(ndr_xa_t *mxa, ndr_hdid_t *mgr_id)
2527961SNatalie.Li@Sun.COM {
2537961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
2547961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
2557961SNatalie.Li@Sun.COM 
2567961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, mgr_id, SVCCTL_MANAGER_CONTEXT);
2577961SNatalie.Li@Sun.COM 	if (hd == NULL)
2587961SNatalie.Li@Sun.COM 		return (NULL);
2597961SNatalie.Li@Sun.COM 
2607961SNatalie.Li@Sun.COM 	mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr;
2617961SNatalie.Li@Sun.COM 
2627961SNatalie.Li@Sun.COM 	return (mgr_ctx);
2637961SNatalie.Li@Sun.COM }
2647961SNatalie.Li@Sun.COM 
2657961SNatalie.Li@Sun.COM /*
2667961SNatalie.Li@Sun.COM  * svcctl_svc_hdalloc
2677961SNatalie.Li@Sun.COM  *
2687961SNatalie.Li@Sun.COM  * Handle allocation wrapper to setup the local service context.
2697961SNatalie.Li@Sun.COM  */
2707961SNatalie.Li@Sun.COM static ndr_hdid_t *
2717961SNatalie.Li@Sun.COM svcctl_svc_hdalloc(ndr_xa_t *mxa, ndr_hdid_t *mgr_id, char *svc_name)
2727961SNatalie.Li@Sun.COM {
2737961SNatalie.Li@Sun.COM 	svcctl_context_t *ctx;
2747961SNatalie.Li@Sun.COM 	svcctl_service_context_t *svc_ctx;
2757961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
2767961SNatalie.Li@Sun.COM 	int max_name_sz = 0;
2777961SNatalie.Li@Sun.COM 	char *svcname;
2787961SNatalie.Li@Sun.COM 
2797961SNatalie.Li@Sun.COM 	mgr_ctx = svcctl_get_mgr_ctx(mxa, mgr_id);
2807961SNatalie.Li@Sun.COM 	if (mgr_ctx == NULL)
2817961SNatalie.Li@Sun.COM 		return (NULL);
2827961SNatalie.Li@Sun.COM 	max_name_sz = mgr_ctx->mc_scf_max_fmri_len;
2837961SNatalie.Li@Sun.COM 
2847961SNatalie.Li@Sun.COM 	if ((ctx = malloc(sizeof (svcctl_context_t))) == NULL) {
2857961SNatalie.Li@Sun.COM 		svcctl_hdfree(mxa, mgr_id);
2867961SNatalie.Li@Sun.COM 		return (NULL);
2877961SNatalie.Li@Sun.COM 	}
2887961SNatalie.Li@Sun.COM 	ctx->c_type = SVCCTL_SERVICE_CONTEXT;
2897961SNatalie.Li@Sun.COM 
2907961SNatalie.Li@Sun.COM 	if ((svc_ctx = malloc(sizeof (svcctl_service_context_t))) == NULL) {
2917961SNatalie.Li@Sun.COM 		svcctl_hdfree(mxa, mgr_id);
2927961SNatalie.Li@Sun.COM 		free(ctx);
2937961SNatalie.Li@Sun.COM 		return (NULL);
2947961SNatalie.Li@Sun.COM 	}
2957961SNatalie.Li@Sun.COM 	bzero(svc_ctx, sizeof (svcctl_service_context_t));
2967961SNatalie.Li@Sun.COM 
2977961SNatalie.Li@Sun.COM 	svc_ctx->sc_mgrid = malloc(sizeof (ndr_hdid_t));
2987961SNatalie.Li@Sun.COM 	svcname = malloc(max_name_sz);
2997961SNatalie.Li@Sun.COM 
3007961SNatalie.Li@Sun.COM 	if ((svc_ctx->sc_mgrid == NULL) || (svcname == NULL)) {
3017961SNatalie.Li@Sun.COM 		free(svc_ctx->sc_mgrid);
3027961SNatalie.Li@Sun.COM 		free(svc_ctx);
3037961SNatalie.Li@Sun.COM 		svcctl_hdfree(mxa, mgr_id);
3047961SNatalie.Li@Sun.COM 		free(ctx);
3057961SNatalie.Li@Sun.COM 		return (NULL);
3067961SNatalie.Li@Sun.COM 	}
3077961SNatalie.Li@Sun.COM 
3087961SNatalie.Li@Sun.COM 	svc_ctx->sc_svcname = svcname;
3097961SNatalie.Li@Sun.COM 
3107961SNatalie.Li@Sun.COM 	bcopy(mgr_id, svc_ctx->sc_mgrid, sizeof (ndr_hdid_t));
3117961SNatalie.Li@Sun.COM 	(void) strlcpy(svc_ctx->sc_svcname, svc_name, max_name_sz);
3127961SNatalie.Li@Sun.COM 
3137961SNatalie.Li@Sun.COM 	ctx->c_ctx.uc_svc = svc_ctx;
3147961SNatalie.Li@Sun.COM 
3157961SNatalie.Li@Sun.COM 	return (ndr_hdalloc(mxa, ctx));
3167961SNatalie.Li@Sun.COM }
3177961SNatalie.Li@Sun.COM 
3187961SNatalie.Li@Sun.COM /*
3197961SNatalie.Li@Sun.COM  * svcctl_s_Close
3207961SNatalie.Li@Sun.COM  *
3217961SNatalie.Li@Sun.COM  * This is a request to close the SVCCTL interface specified by the
3227961SNatalie.Li@Sun.COM  * handle. Free the handle and zero out the result handle for the
3237961SNatalie.Li@Sun.COM  * client.
3247961SNatalie.Li@Sun.COM  *
3257961SNatalie.Li@Sun.COM  * Returns:
3267961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
3277961SNatalie.Li@Sun.COM  *	ERROR_INVALID_HANDLE
3287961SNatalie.Li@Sun.COM  */
3297961SNatalie.Li@Sun.COM static int
3308334SJose.Borrego@Sun.COM svcctl_s_Close(void *arg, ndr_xa_t *mxa)
3317961SNatalie.Li@Sun.COM {
3327961SNatalie.Li@Sun.COM 	struct svcctl_Close *param = arg;
3337961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
3347961SNatalie.Li@Sun.COM 
3357961SNatalie.Li@Sun.COM 	svcctl_hdfree(mxa, id);
3367961SNatalie.Li@Sun.COM 
3377961SNatalie.Li@Sun.COM 	bzero(&param->result_handle, sizeof (svcctl_handle_t));
3387961SNatalie.Li@Sun.COM 	param->status = ERROR_SUCCESS;
3398334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
3407961SNatalie.Li@Sun.COM }
3417961SNatalie.Li@Sun.COM 
3427961SNatalie.Li@Sun.COM /*
34310001SJoyce.McIntosh@Sun.COM  * svcctl_s_ControlService
34410001SJoyce.McIntosh@Sun.COM  */
34510001SJoyce.McIntosh@Sun.COM static int
34610001SJoyce.McIntosh@Sun.COM svcctl_s_ControlService(void *arg, ndr_xa_t *mxa)
34710001SJoyce.McIntosh@Sun.COM {
34810001SJoyce.McIntosh@Sun.COM 	struct svcctl_ControlService *param = arg;
34910001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
35010001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
35110001SJoyce.McIntosh@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
35210001SJoyce.McIntosh@Sun.COM 	svcctl_service_context_t *svc_ctx;
35310001SJoyce.McIntosh@Sun.COM 	svcctl_svc_node_t *svc;
35410001SJoyce.McIntosh@Sun.COM 
35510001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
35610001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
35710001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_ControlService));
35810001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
35910001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
36010001SJoyce.McIntosh@Sun.COM 	}
36110001SJoyce.McIntosh@Sun.COM 
36210001SJoyce.McIntosh@Sun.COM 	svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc;
36310001SJoyce.McIntosh@Sun.COM 	mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid);
36410001SJoyce.McIntosh@Sun.COM 	if (mgr_ctx == NULL) {
36510001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_ControlService));
36610001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
36710001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
36810001SJoyce.McIntosh@Sun.COM 	}
36910001SJoyce.McIntosh@Sun.COM 
37010001SJoyce.McIntosh@Sun.COM 	switch (param->control) {
37110001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_STOP:
37210001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_PAUSE:
37310001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_CONTINUE:
37410001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_INTERROGATE:
37510001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_SHUTDOWN:
37610001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_PARAMCHANGE:
37710001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_NETBINDADD:
37810001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_NETBINDREMOVE:
37910001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_NETBINDENABLE:
38010001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTROL_NETBINDDISABLE:
38110001SJoyce.McIntosh@Sun.COM 		break;
38210001SJoyce.McIntosh@Sun.COM 	default:
38310001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_ControlService));
38410001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_PARAMETER;
38510001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
38610001SJoyce.McIntosh@Sun.COM 	}
38710001SJoyce.McIntosh@Sun.COM 
38810001SJoyce.McIntosh@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname);
38910001SJoyce.McIntosh@Sun.COM 	if (svc == NULL || svc->sn_state == NULL) {
39010001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_ControlService));
39110001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_SERVICE_DOES_NOT_EXIST;
39210001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
39310001SJoyce.McIntosh@Sun.COM 	}
39410001SJoyce.McIntosh@Sun.COM 
39510001SJoyce.McIntosh@Sun.COM 	param->service_status.service_type = SERVICE_WIN32_SHARE_PROCESS;
39610001SJoyce.McIntosh@Sun.COM 	param->service_status.cur_state = svcctl_scm_map_status(svc->sn_state);
39710001SJoyce.McIntosh@Sun.COM 	param->service_status.ctrl_accepted = 0;
39810001SJoyce.McIntosh@Sun.COM 	param->service_status.w32_exitcode = 0;
39910001SJoyce.McIntosh@Sun.COM 	param->service_status.svc_specified_exitcode = 0;
40010001SJoyce.McIntosh@Sun.COM 	param->service_status.check_point = 0;
40110001SJoyce.McIntosh@Sun.COM 	param->service_status.wait_hint = 0;
40210001SJoyce.McIntosh@Sun.COM 
40310001SJoyce.McIntosh@Sun.COM 	param->status = ERROR_SUCCESS;
40410001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
40510001SJoyce.McIntosh@Sun.COM }
40610001SJoyce.McIntosh@Sun.COM 
40710001SJoyce.McIntosh@Sun.COM /*
40810001SJoyce.McIntosh@Sun.COM  * svcctl_s_DeleteService
40910001SJoyce.McIntosh@Sun.COM  */
41010001SJoyce.McIntosh@Sun.COM static int
41110001SJoyce.McIntosh@Sun.COM svcctl_s_DeleteService(void *arg, ndr_xa_t *mxa)
41210001SJoyce.McIntosh@Sun.COM {
41310001SJoyce.McIntosh@Sun.COM 	struct svcctl_DeleteService *param = arg;
41410001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
41510001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
41610001SJoyce.McIntosh@Sun.COM 
41710001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
41810001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
41910001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
42010001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
42110001SJoyce.McIntosh@Sun.COM 	}
42210001SJoyce.McIntosh@Sun.COM 
42310001SJoyce.McIntosh@Sun.COM 	param->status = ERROR_SUCCESS;
42410001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
42510001SJoyce.McIntosh@Sun.COM }
42610001SJoyce.McIntosh@Sun.COM 
42710001SJoyce.McIntosh@Sun.COM /*
42810001SJoyce.McIntosh@Sun.COM  * svcctl_s_QueryServiceSecurity
42910001SJoyce.McIntosh@Sun.COM  */
43010001SJoyce.McIntosh@Sun.COM static int
43110001SJoyce.McIntosh@Sun.COM svcctl_s_QueryServiceSecurity(void *arg, ndr_xa_t *mxa)
43210001SJoyce.McIntosh@Sun.COM {
43310001SJoyce.McIntosh@Sun.COM 	struct svcctl_QueryServiceSecurity *param = arg;
43410001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
43510001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
43610001SJoyce.McIntosh@Sun.COM 	uint32_t sec_info;
43710001SJoyce.McIntosh@Sun.COM 	uint32_t bytes_needed = 0;
43810001SJoyce.McIntosh@Sun.COM 	uint32_t status;
43910001SJoyce.McIntosh@Sun.COM 
44010001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
44110001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
44210001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
44310001SJoyce.McIntosh@Sun.COM 		goto query_service_security_error;
44410001SJoyce.McIntosh@Sun.COM 	}
44510001SJoyce.McIntosh@Sun.COM 
44610001SJoyce.McIntosh@Sun.COM 	sec_info = param->security_info & SMB_ALL_SECINFO;
44710001SJoyce.McIntosh@Sun.COM 	if (sec_info == 0) {
44810001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_PARAMETER;
44910001SJoyce.McIntosh@Sun.COM 		goto query_service_security_error;
45010001SJoyce.McIntosh@Sun.COM 	}
45110001SJoyce.McIntosh@Sun.COM 
45210001SJoyce.McIntosh@Sun.COM 	if (param->buf_size < SVCCTL_SECURITY_BUFSIZE) {
45310001SJoyce.McIntosh@Sun.COM 		bytes_needed = SVCCTL_SECURITY_BUFSIZE;
45410001SJoyce.McIntosh@Sun.COM 		status = ERROR_INSUFFICIENT_BUFFER;
45510001SJoyce.McIntosh@Sun.COM 		goto query_service_security_error;
45610001SJoyce.McIntosh@Sun.COM 	}
45710001SJoyce.McIntosh@Sun.COM 
45810001SJoyce.McIntosh@Sun.COM 	param->buffer = NDR_MALLOC(mxa, SVCCTL_SECURITY_BUFSIZE);
45910001SJoyce.McIntosh@Sun.COM 	if (param->buffer == NULL) {
46010001SJoyce.McIntosh@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
46110001SJoyce.McIntosh@Sun.COM 		goto query_service_security_error;
46210001SJoyce.McIntosh@Sun.COM 	}
46310001SJoyce.McIntosh@Sun.COM 
46410001SJoyce.McIntosh@Sun.COM 	bzero(param->buffer, sizeof (SVCCTL_SECURITY_BUFSIZE));
46510001SJoyce.McIntosh@Sun.COM 	param->buf_size = SVCCTL_SECURITY_BUFSIZE;
46610001SJoyce.McIntosh@Sun.COM 	param->bytes_needed = 0;
46710001SJoyce.McIntosh@Sun.COM 	param->status = ERROR_SUCCESS;
46810001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
46910001SJoyce.McIntosh@Sun.COM 
47010001SJoyce.McIntosh@Sun.COM query_service_security_error:
47110001SJoyce.McIntosh@Sun.COM 	bzero(param, sizeof (struct svcctl_QueryServiceSecurity));
47210001SJoyce.McIntosh@Sun.COM 	param->buf_size = 0;
47310001SJoyce.McIntosh@Sun.COM 	param->buffer = NDR_MALLOC(mxa, sizeof (uint32_t));
47410001SJoyce.McIntosh@Sun.COM 	param->bytes_needed = bytes_needed;
47510001SJoyce.McIntosh@Sun.COM 	param->status = status;
47610001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
47710001SJoyce.McIntosh@Sun.COM }
47810001SJoyce.McIntosh@Sun.COM 
47910001SJoyce.McIntosh@Sun.COM 
48010001SJoyce.McIntosh@Sun.COM /*
48110001SJoyce.McIntosh@Sun.COM  * svcctl_s_SetServiceSecurity
48210001SJoyce.McIntosh@Sun.COM  */
48310001SJoyce.McIntosh@Sun.COM static int
48410001SJoyce.McIntosh@Sun.COM svcctl_s_SetServiceSecurity(void *arg, ndr_xa_t *mxa)
48510001SJoyce.McIntosh@Sun.COM {
48610001SJoyce.McIntosh@Sun.COM 	struct svcctl_SetServiceSecurity *param = arg;
48710001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
48810001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
48910001SJoyce.McIntosh@Sun.COM 
49010001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
49110001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
49210001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
49310001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
49410001SJoyce.McIntosh@Sun.COM 	}
49510001SJoyce.McIntosh@Sun.COM 
49610001SJoyce.McIntosh@Sun.COM 	if ((param->security_info & SMB_ALL_SECINFO) == 0) {
49710001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_PARAMETER;
49810001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
49910001SJoyce.McIntosh@Sun.COM 	}
50010001SJoyce.McIntosh@Sun.COM 
50110001SJoyce.McIntosh@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
50210001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
50310001SJoyce.McIntosh@Sun.COM }
50410001SJoyce.McIntosh@Sun.COM 
50510001SJoyce.McIntosh@Sun.COM /*
5067961SNatalie.Li@Sun.COM  * svcctl_s_OpenManager
5077961SNatalie.Li@Sun.COM  *
5087961SNatalie.Li@Sun.COM  * Request to open the service control manager.
5097961SNatalie.Li@Sun.COM  * The caller must have administrator rights in order to open this
5107961SNatalie.Li@Sun.COM  * interface.  We don't support write (SC_MANAGER_LOCK) access.
5117961SNatalie.Li@Sun.COM  *
5127961SNatalie.Li@Sun.COM  * Returns:
5137961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
5147961SNatalie.Li@Sun.COM  *	ERROR_ACCESS_DENIED
5157961SNatalie.Li@Sun.COM  *
5167961SNatalie.Li@Sun.COM  * On success, returns a handle for use with subsequent svcctl requests.
5177961SNatalie.Li@Sun.COM  */
5187961SNatalie.Li@Sun.COM static int
5198334SJose.Borrego@Sun.COM svcctl_s_OpenManager(void *arg, ndr_xa_t *mxa)
5207961SNatalie.Li@Sun.COM {
5217961SNatalie.Li@Sun.COM 	struct svcctl_OpenManager *param = arg;
5227961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = NULL;
5237961SNatalie.Li@Sun.COM 	int rc;
5247961SNatalie.Li@Sun.COM 
5257961SNatalie.Li@Sun.COM 	rc = ndr_is_admin(mxa);
5267961SNatalie.Li@Sun.COM 
5277961SNatalie.Li@Sun.COM 	if ((rc == 0) || (param->desired_access & SC_MANAGER_LOCK) != 0) {
5287961SNatalie.Li@Sun.COM 		bzero(&param->handle, sizeof (svcctl_handle_t));
5297961SNatalie.Li@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
5308334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5317961SNatalie.Li@Sun.COM 	}
5327961SNatalie.Li@Sun.COM 
5337961SNatalie.Li@Sun.COM 	id = svcctl_mgr_hdalloc(mxa);
5347961SNatalie.Li@Sun.COM 	if (id) {
5357961SNatalie.Li@Sun.COM 		bcopy(id, &param->handle, sizeof (svcctl_handle_t));
5367961SNatalie.Li@Sun.COM 		param->status = ERROR_SUCCESS;
5377961SNatalie.Li@Sun.COM 	} else {
5387961SNatalie.Li@Sun.COM 		bzero(&param->handle, sizeof (svcctl_handle_t));
5397961SNatalie.Li@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
5407961SNatalie.Li@Sun.COM 	}
5417961SNatalie.Li@Sun.COM 
5428334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
5437961SNatalie.Li@Sun.COM }
5447961SNatalie.Li@Sun.COM 
5457961SNatalie.Li@Sun.COM /*
5467961SNatalie.Li@Sun.COM  * svcctl_s_OpenService
5477961SNatalie.Li@Sun.COM  *
5487961SNatalie.Li@Sun.COM  * Return a handle for use with subsequent svcctl requests.
5497961SNatalie.Li@Sun.COM  *
5507961SNatalie.Li@Sun.COM  * Returns:
5517961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
5527961SNatalie.Li@Sun.COM  *	ERROR_INVALID_HANDLE
5537961SNatalie.Li@Sun.COM  *	ERROR_SERVICE_DOES_NOT_EXIST
5547961SNatalie.Li@Sun.COM  *	ERROR_CALL_NOT_IMPLEMENTED
5557961SNatalie.Li@Sun.COM  */
5567961SNatalie.Li@Sun.COM static int
5578334SJose.Borrego@Sun.COM svcctl_s_OpenService(void *arg, ndr_xa_t *mxa)
5587961SNatalie.Li@Sun.COM {
5597961SNatalie.Li@Sun.COM 	struct svcctl_OpenService *param = arg;
5607961SNatalie.Li@Sun.COM 	ndr_hdid_t *mgrid = (ndr_hdid_t *)&param->manager_handle;
5617961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = NULL;
5627961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
5637961SNatalie.Li@Sun.COM 	DWORD status;
5647961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
5657961SNatalie.Li@Sun.COM 	char *svc_name = (char *)param->service_name;
5667961SNatalie.Li@Sun.COM 	boolean_t unimplemented_operations = B_FALSE;
5677961SNatalie.Li@Sun.COM 
5687961SNatalie.Li@Sun.COM 	/* Allow service handle allocations for only status & config queries */
5697961SNatalie.Li@Sun.COM 	unimplemented_operations =
5707961SNatalie.Li@Sun.COM 	    SVCCTL_OPENSVC_OP_UNIMPLEMENTED(param->desired_access);
5717961SNatalie.Li@Sun.COM 
5727961SNatalie.Li@Sun.COM 	if (unimplemented_operations) {
5737961SNatalie.Li@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
5747961SNatalie.Li@Sun.COM 		param->status = ERROR_CALL_NOT_IMPLEMENTED;
5758334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5767961SNatalie.Li@Sun.COM 	}
5777961SNatalie.Li@Sun.COM 
5787961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, mgrid, SVCCTL_MANAGER_CONTEXT);
5797961SNatalie.Li@Sun.COM 	if (hd == NULL) {
5807961SNatalie.Li@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
5817961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
5828334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5837961SNatalie.Li@Sun.COM 	}
5847961SNatalie.Li@Sun.COM 
5857961SNatalie.Li@Sun.COM 	mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr;
5867961SNatalie.Li@Sun.COM 	status = svcctl_scm_validate_service(mgr_ctx, svc_name);
5877961SNatalie.Li@Sun.COM 	if (status != ERROR_SUCCESS) {
5887961SNatalie.Li@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
5897961SNatalie.Li@Sun.COM 		param->status = status;
5908334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5917961SNatalie.Li@Sun.COM 	}
5927961SNatalie.Li@Sun.COM 
5937961SNatalie.Li@Sun.COM 	id = svcctl_svc_hdalloc(mxa, mgrid, svc_name);
5947961SNatalie.Li@Sun.COM 	if (id) {
5957961SNatalie.Li@Sun.COM 		bcopy(id, &param->service_handle, sizeof (svcctl_handle_t));
5967961SNatalie.Li@Sun.COM 		param->status = ERROR_SUCCESS;
5977961SNatalie.Li@Sun.COM 	} else {
5987961SNatalie.Li@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
5997961SNatalie.Li@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
6007961SNatalie.Li@Sun.COM 	}
6017961SNatalie.Li@Sun.COM 
6028334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6037961SNatalie.Li@Sun.COM }
6047961SNatalie.Li@Sun.COM 
6057961SNatalie.Li@Sun.COM /*
6067961SNatalie.Li@Sun.COM  * svcctl_s_QueryServiceStatus
6077961SNatalie.Li@Sun.COM  *
6087961SNatalie.Li@Sun.COM  * Returns:
6097961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
6107961SNatalie.Li@Sun.COM  *	ERROR_INVALID_HANDLE
6117961SNatalie.Li@Sun.COM  */
6127961SNatalie.Li@Sun.COM static int
6138334SJose.Borrego@Sun.COM svcctl_s_QueryServiceStatus(void *arg, ndr_xa_t *mxa)
6147961SNatalie.Li@Sun.COM {
6157961SNatalie.Li@Sun.COM 	struct svcctl_QueryServiceStatus *param = arg;
6167961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
6177961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
6187961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
6197961SNatalie.Li@Sun.COM 	svcctl_service_context_t *svc_ctx;
6207961SNatalie.Li@Sun.COM 	svcctl_svc_node_t *svc;
6217961SNatalie.Li@Sun.COM 
6227961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
6237961SNatalie.Li@Sun.COM 	if (hd == NULL) {
6247961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceStatus));
6257961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
6268334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6277961SNatalie.Li@Sun.COM 	}
6287961SNatalie.Li@Sun.COM 
6297961SNatalie.Li@Sun.COM 	svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc;
6307961SNatalie.Li@Sun.COM 	mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid);
6317961SNatalie.Li@Sun.COM 	if (mgr_ctx == NULL) {
63210001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceStatus));
6337961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
6348334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6357961SNatalie.Li@Sun.COM 	}
6367961SNatalie.Li@Sun.COM 
6377961SNatalie.Li@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname);
6387961SNatalie.Li@Sun.COM 	if (svc == NULL || svc->sn_state == NULL) {
63910001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceStatus));
6407961SNatalie.Li@Sun.COM 		param->status = ERROR_SERVICE_DOES_NOT_EXIST;
6418334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6427961SNatalie.Li@Sun.COM 	}
6437961SNatalie.Li@Sun.COM 
6447961SNatalie.Li@Sun.COM 	param->service_status.service_type = SERVICE_WIN32_SHARE_PROCESS;
6457961SNatalie.Li@Sun.COM 	param->service_status.cur_state = svcctl_scm_map_status(svc->sn_state);
6467961SNatalie.Li@Sun.COM 	param->service_status.ctrl_accepted = 0;
6477961SNatalie.Li@Sun.COM 	param->service_status.w32_exitcode = 0;
6487961SNatalie.Li@Sun.COM 	param->service_status.svc_specified_exitcode = 0;
6497961SNatalie.Li@Sun.COM 	param->service_status.check_point = 0;
6507961SNatalie.Li@Sun.COM 	param->service_status.wait_hint = 0;
6517961SNatalie.Li@Sun.COM 
6527961SNatalie.Li@Sun.COM 	param->status = ERROR_SUCCESS;
6538334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6547961SNatalie.Li@Sun.COM }
6557961SNatalie.Li@Sun.COM 
6567961SNatalie.Li@Sun.COM /*
65710001SJoyce.McIntosh@Sun.COM  * svcctl_s_EnumDependentServices
65810001SJoyce.McIntosh@Sun.COM  *
65910001SJoyce.McIntosh@Sun.COM  * Enumerate the list of services that depend on the specified service.
66010001SJoyce.McIntosh@Sun.COM  */
66110001SJoyce.McIntosh@Sun.COM static int
66210001SJoyce.McIntosh@Sun.COM svcctl_s_EnumDependentServices(void *arg, ndr_xa_t *mxa)
66310001SJoyce.McIntosh@Sun.COM {
66410001SJoyce.McIntosh@Sun.COM 	struct svcctl_EnumDependentServices *param = arg;
66510001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
66610001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
66710001SJoyce.McIntosh@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
66810001SJoyce.McIntosh@Sun.COM 	svcctl_service_context_t *svc_ctx;
66910001SJoyce.McIntosh@Sun.COM 	svcctl_svc_node_t *svc;
67010001SJoyce.McIntosh@Sun.COM 	int input_bufsize = 0;
67110001SJoyce.McIntosh@Sun.COM 	uint32_t status;
67210001SJoyce.McIntosh@Sun.COM 
67310001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
67410001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
67510001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
67610001SJoyce.McIntosh@Sun.COM 		goto enum_dependent_services_error;
67710001SJoyce.McIntosh@Sun.COM 	}
67810001SJoyce.McIntosh@Sun.COM 
67910001SJoyce.McIntosh@Sun.COM 	svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc;
68010001SJoyce.McIntosh@Sun.COM 	mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid);
68110001SJoyce.McIntosh@Sun.COM 	if (mgr_ctx == NULL) {
68210001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
68310001SJoyce.McIntosh@Sun.COM 		goto enum_dependent_services_error;
68410001SJoyce.McIntosh@Sun.COM 	}
68510001SJoyce.McIntosh@Sun.COM 
68610001SJoyce.McIntosh@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname);
68710001SJoyce.McIntosh@Sun.COM 	if (svc == NULL || svc->sn_state == NULL) {
68810001SJoyce.McIntosh@Sun.COM 		status = ERROR_SERVICE_DOES_NOT_EXIST;
68910001SJoyce.McIntosh@Sun.COM 		goto enum_dependent_services_error;
69010001SJoyce.McIntosh@Sun.COM 	}
69110001SJoyce.McIntosh@Sun.COM 
69210001SJoyce.McIntosh@Sun.COM 	switch (param->svc_state) {
69310001SJoyce.McIntosh@Sun.COM 	case SERVICE_STOPPED:
69410001SJoyce.McIntosh@Sun.COM 	case SERVICE_START_PENDING:
69510001SJoyce.McIntosh@Sun.COM 	case SERVICE_STOP_PENDING:
69610001SJoyce.McIntosh@Sun.COM 	case SERVICE_RUNNING:
69710001SJoyce.McIntosh@Sun.COM 	case SERVICE_CONTINUE_PENDING:
69810001SJoyce.McIntosh@Sun.COM 	case SERVICE_PAUSE_PENDING:
69910001SJoyce.McIntosh@Sun.COM 	case SERVICE_PAUSED:
70010001SJoyce.McIntosh@Sun.COM 		break;
70110001SJoyce.McIntosh@Sun.COM 	default:
70210001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_PARAMETER;
70310001SJoyce.McIntosh@Sun.COM 		goto enum_dependent_services_error;
70410001SJoyce.McIntosh@Sun.COM 	}
70510001SJoyce.McIntosh@Sun.COM 
70610001SJoyce.McIntosh@Sun.COM 	if ((input_bufsize = param->buf_size) == 0) {
70710001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_EnumDependentServices));
70810001SJoyce.McIntosh@Sun.COM 		param->buf_size = input_bufsize;
70910001SJoyce.McIntosh@Sun.COM 		param->services = NDR_STRDUP(mxa, "");
71010001SJoyce.McIntosh@Sun.COM 		param->bytes_needed = 1024;
71110001SJoyce.McIntosh@Sun.COM 		param->svc_num = 0;
71210001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_MORE_DATA;
71310001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
71410001SJoyce.McIntosh@Sun.COM 	}
71510001SJoyce.McIntosh@Sun.COM 
71610001SJoyce.McIntosh@Sun.COM 	param->services = NDR_MALLOC(mxa, input_bufsize);
71710001SJoyce.McIntosh@Sun.COM 	if (param->services == NULL) {
71810001SJoyce.McIntosh@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
71910001SJoyce.McIntosh@Sun.COM 		goto enum_dependent_services_error;
72010001SJoyce.McIntosh@Sun.COM 	}
72110001SJoyce.McIntosh@Sun.COM 
72210001SJoyce.McIntosh@Sun.COM 	bzero(param->services, input_bufsize);
72310001SJoyce.McIntosh@Sun.COM 	param->buf_size = input_bufsize;
72410001SJoyce.McIntosh@Sun.COM 	param->bytes_needed = 0;
72510001SJoyce.McIntosh@Sun.COM 	param->svc_num = 0;
72610001SJoyce.McIntosh@Sun.COM 	param->status = ERROR_SUCCESS;
72710001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
72810001SJoyce.McIntosh@Sun.COM 
72910001SJoyce.McIntosh@Sun.COM enum_dependent_services_error:
73010001SJoyce.McIntosh@Sun.COM 	bzero(param, sizeof (struct svcctl_EnumDependentServices));
73110001SJoyce.McIntosh@Sun.COM 	param->services = NDR_STRDUP(mxa, "");
73210001SJoyce.McIntosh@Sun.COM 	param->status = status;
73310001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
73410001SJoyce.McIntosh@Sun.COM }
73510001SJoyce.McIntosh@Sun.COM 
73610001SJoyce.McIntosh@Sun.COM /*
7377961SNatalie.Li@Sun.COM  * svcctl_s_EnumServicesStatus
7387961SNatalie.Li@Sun.COM  *
73910001SJoyce.McIntosh@Sun.COM  * Enumerate the list of services we support.
7407961SNatalie.Li@Sun.COM  */
7417961SNatalie.Li@Sun.COM static int
7428334SJose.Borrego@Sun.COM svcctl_s_EnumServicesStatus(void *arg, ndr_xa_t *mxa)
7437961SNatalie.Li@Sun.COM {
7447961SNatalie.Li@Sun.COM 	struct svcctl_EnumServicesStatus *param = arg;
7457961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->manager_handle;
7467961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
7477961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
74810001SJoyce.McIntosh@Sun.COM 	uint32_t buf_size = 0;
74910001SJoyce.McIntosh@Sun.COM 	uint32_t svc_num;
75010001SJoyce.McIntosh@Sun.COM 	uint32_t resume_handle = 0;
75110001SJoyce.McIntosh@Sun.COM 	uint32_t status;
75210001SJoyce.McIntosh@Sun.COM 
75310001SJoyce.McIntosh@Sun.COM 	if (param->resume_handle != NULL)
75410001SJoyce.McIntosh@Sun.COM 		resume_handle = *param->resume_handle;
7557961SNatalie.Li@Sun.COM 
7567961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_MANAGER_CONTEXT);
7577961SNatalie.Li@Sun.COM 	if (hd == NULL) {
75810001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
75910001SJoyce.McIntosh@Sun.COM 		goto enum_services_status_error;
7607961SNatalie.Li@Sun.COM 	}
7617961SNatalie.Li@Sun.COM 
7627961SNatalie.Li@Sun.COM 	mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr;
7637961SNatalie.Li@Sun.COM 	if (svcctl_scm_refresh(mgr_ctx) != 0) {
76410001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
76510001SJoyce.McIntosh@Sun.COM 		goto enum_services_status_error;
7667961SNatalie.Li@Sun.COM 	}
7677961SNatalie.Li@Sun.COM 
76810001SJoyce.McIntosh@Sun.COM 	buf_size = param->buf_size;
76910001SJoyce.McIntosh@Sun.COM 	param->services = NDR_MALLOC(mxa, buf_size);
7707961SNatalie.Li@Sun.COM 	if (param->services == NULL) {
77110001SJoyce.McIntosh@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
77210001SJoyce.McIntosh@Sun.COM 		goto enum_services_status_error;
7737961SNatalie.Li@Sun.COM 	}
77410001SJoyce.McIntosh@Sun.COM 	bzero(param->services, buf_size);
7757961SNatalie.Li@Sun.COM 
77610001SJoyce.McIntosh@Sun.COM 	if (buf_size < SVCCTL_ENUMSERVICES_MINBUFSIZE) {
7777961SNatalie.Li@Sun.COM 		param->bytes_needed = mgr_ctx->mc_bytes_needed;
7787961SNatalie.Li@Sun.COM 		param->svc_num = 0;
77910001SJoyce.McIntosh@Sun.COM 		if (param->resume_handle)
78010001SJoyce.McIntosh@Sun.COM 			*param->resume_handle = 0;
7817961SNatalie.Li@Sun.COM 		param->status = ERROR_MORE_DATA;
7828334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
7837961SNatalie.Li@Sun.COM 	}
7847961SNatalie.Li@Sun.COM 
78510001SJoyce.McIntosh@Sun.COM 	svc_num = svcctl_scm_enum_services(mgr_ctx, param->services,
78610001SJoyce.McIntosh@Sun.COM 	    buf_size, &resume_handle, B_TRUE);
78710001SJoyce.McIntosh@Sun.COM 
78810001SJoyce.McIntosh@Sun.COM 	param->buf_size = buf_size;
78910001SJoyce.McIntosh@Sun.COM 	param->svc_num = svc_num;
7907961SNatalie.Li@Sun.COM 
79110001SJoyce.McIntosh@Sun.COM 	if (resume_handle != 0) {
79210001SJoyce.McIntosh@Sun.COM 		if (param->resume_handle != NULL)
79310001SJoyce.McIntosh@Sun.COM 			*param->resume_handle = resume_handle;
79410001SJoyce.McIntosh@Sun.COM 		param->bytes_needed = mgr_ctx->mc_bytes_needed;
79510001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_MORE_DATA;
79610001SJoyce.McIntosh@Sun.COM 	} else {
79710001SJoyce.McIntosh@Sun.COM 		if (param->resume_handle)
79810001SJoyce.McIntosh@Sun.COM 			*param->resume_handle = 0;
79910001SJoyce.McIntosh@Sun.COM 		param->bytes_needed = 0;
80010001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_SUCCESS;
80110001SJoyce.McIntosh@Sun.COM 	}
80210001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
80310001SJoyce.McIntosh@Sun.COM 
80410001SJoyce.McIntosh@Sun.COM enum_services_status_error:
80510001SJoyce.McIntosh@Sun.COM 	bzero(param, sizeof (struct svcctl_EnumServicesStatus));
80610001SJoyce.McIntosh@Sun.COM 	param->services = NDR_STRDUP(mxa, "");
80710001SJoyce.McIntosh@Sun.COM 	param->status = status;
8088334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
8097961SNatalie.Li@Sun.COM }
8107961SNatalie.Li@Sun.COM 
8117961SNatalie.Li@Sun.COM /*
8127961SNatalie.Li@Sun.COM  * svcctl_s_QueryServiceConfig
8137961SNatalie.Li@Sun.COM  *
8147961SNatalie.Li@Sun.COM  * Returns:
8157961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
8167961SNatalie.Li@Sun.COM  *	ERROR_INVALID_HANDLE
8177961SNatalie.Li@Sun.COM  */
8187961SNatalie.Li@Sun.COM static int
8198334SJose.Borrego@Sun.COM svcctl_s_QueryServiceConfig(void *arg, ndr_xa_t *mxa)
8207961SNatalie.Li@Sun.COM {
8217961SNatalie.Li@Sun.COM 	struct svcctl_QueryServiceConfig *param = arg;
8227961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
8237961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
8247961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
8257961SNatalie.Li@Sun.COM 	svcctl_service_context_t *svc_ctx;
8267961SNatalie.Li@Sun.COM 	svcctl_svc_node_t *svc;
8277961SNatalie.Li@Sun.COM 	int bytes_needed = 0;
8287961SNatalie.Li@Sun.COM 	svc_config_t *cfg;
8297961SNatalie.Li@Sun.COM 
8307961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
8317961SNatalie.Li@Sun.COM 	if (hd == NULL) {
8327961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceConfig));
8337961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
8348334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8357961SNatalie.Li@Sun.COM 	}
8367961SNatalie.Li@Sun.COM 
8377961SNatalie.Li@Sun.COM 	svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc;
8387961SNatalie.Li@Sun.COM 	mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid);
8397961SNatalie.Li@Sun.COM 	if (mgr_ctx == NULL) {
8407961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceConfig));
8417961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
8428334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8437961SNatalie.Li@Sun.COM 	}
8447961SNatalie.Li@Sun.COM 
8457961SNatalie.Li@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname);
8467961SNatalie.Li@Sun.COM 	if (svc == NULL || svc->sn_fmri == NULL) {
8477961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceConfig));
8487961SNatalie.Li@Sun.COM 		param->status = ERROR_SERVICE_DOES_NOT_EXIST;
8498334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8507961SNatalie.Li@Sun.COM 	}
8517961SNatalie.Li@Sun.COM 
8527961SNatalie.Li@Sun.COM 	cfg = &param->service_cfg;
8537961SNatalie.Li@Sun.COM 	cfg->service_type = SERVICE_WIN32_SHARE_PROCESS;
8547961SNatalie.Li@Sun.COM 	cfg->start_type = SERVICE_AUTO_START;
85510504SKeyur.Desai@Sun.COM 	cfg->error_control = SERVICE_ERROR_IGNORE;
8568334SJose.Borrego@Sun.COM 	cfg->binary_pathname = NDR_STRDUP(mxa, "");
8578334SJose.Borrego@Sun.COM 	cfg->loadorder_group = NDR_STRDUP(mxa, "");
8587961SNatalie.Li@Sun.COM 	cfg->tag_id = 0;
8598334SJose.Borrego@Sun.COM 	cfg->dependencies = NDR_STRDUP(mxa, "");
8608334SJose.Borrego@Sun.COM 	cfg->service_startname = NDR_STRDUP(mxa, "");
8618334SJose.Borrego@Sun.COM 	cfg->display_name = NDR_STRDUP(mxa, svc->sn_fmri);
8627961SNatalie.Li@Sun.COM 
8637961SNatalie.Li@Sun.COM 	bytes_needed = sizeof (svc_config_t);
8647961SNatalie.Li@Sun.COM 	bytes_needed += SVCCTL_WNSTRLEN((const char *)cfg->binary_pathname);
8657961SNatalie.Li@Sun.COM 	bytes_needed += SVCCTL_WNSTRLEN((const char *)cfg->loadorder_group);
8667961SNatalie.Li@Sun.COM 	bytes_needed += SVCCTL_WNSTRLEN((const char *)cfg->dependencies);
8677961SNatalie.Li@Sun.COM 	bytes_needed += SVCCTL_WNSTRLEN((const char *)cfg->service_startname);
8687961SNatalie.Li@Sun.COM 	bytes_needed += SVCCTL_WNSTRLEN(svc->sn_fmri);
8697961SNatalie.Li@Sun.COM 
8707961SNatalie.Li@Sun.COM 	if (param->buf_size < bytes_needed) {
8717961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceConfig));
8727961SNatalie.Li@Sun.COM 		param->cfg_bytes = bytes_needed;
87310001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INSUFFICIENT_BUFFER;
8748334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8757961SNatalie.Li@Sun.COM 	}
8767961SNatalie.Li@Sun.COM 
8777961SNatalie.Li@Sun.COM 	param->cfg_bytes = bytes_needed;
8787961SNatalie.Li@Sun.COM 	param->status = ERROR_SUCCESS;
8798334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
8807961SNatalie.Li@Sun.COM }
8817961SNatalie.Li@Sun.COM 
8827961SNatalie.Li@Sun.COM /*
88310001SJoyce.McIntosh@Sun.COM  * svcctl_s_StartService
88410001SJoyce.McIntosh@Sun.COM  */
88510001SJoyce.McIntosh@Sun.COM static int
88610001SJoyce.McIntosh@Sun.COM svcctl_s_StartService(void *arg, ndr_xa_t *mxa)
88710001SJoyce.McIntosh@Sun.COM {
88810001SJoyce.McIntosh@Sun.COM 	struct svcctl_StartService *param = arg;
88910001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
89010001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
89110001SJoyce.McIntosh@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
89210001SJoyce.McIntosh@Sun.COM 	svcctl_service_context_t *svc_ctx;
89310001SJoyce.McIntosh@Sun.COM 	svcctl_svc_node_t *svc;
89410001SJoyce.McIntosh@Sun.COM 
89510001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
89610001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
89710001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
89810001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
89910001SJoyce.McIntosh@Sun.COM 	}
90010001SJoyce.McIntosh@Sun.COM 
90110001SJoyce.McIntosh@Sun.COM 	svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc;
90210001SJoyce.McIntosh@Sun.COM 	mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid);
90310001SJoyce.McIntosh@Sun.COM 	if (mgr_ctx == NULL) {
90410001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
90510001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
90610001SJoyce.McIntosh@Sun.COM 	}
90710001SJoyce.McIntosh@Sun.COM 
90810001SJoyce.McIntosh@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname);
90910001SJoyce.McIntosh@Sun.COM 	if (svc == NULL || svc->sn_fmri == NULL)
91010001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_SERVICE_DOES_NOT_EXIST;
91110001SJoyce.McIntosh@Sun.COM 	else
91210001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_SERVICE_ALREADY_RUNNING;
91310001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
91410001SJoyce.McIntosh@Sun.COM }
91510001SJoyce.McIntosh@Sun.COM 
91610001SJoyce.McIntosh@Sun.COM 
91710001SJoyce.McIntosh@Sun.COM /*
9187961SNatalie.Li@Sun.COM  * svcctl_s_GetServiceDisplayNameW
9197961SNatalie.Li@Sun.COM  *
9207961SNatalie.Li@Sun.COM  * Returns:
9217961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
9227961SNatalie.Li@Sun.COM  *	ERROR_INVALID_HANDLE
9237961SNatalie.Li@Sun.COM  *	ERROR_SERVICE_DOES_NOT_EXIST
9247961SNatalie.Li@Sun.COM  */
9257961SNatalie.Li@Sun.COM static int
9268334SJose.Borrego@Sun.COM svcctl_s_GetServiceDisplayNameW(void *arg, ndr_xa_t *mxa)
9277961SNatalie.Li@Sun.COM {
9287961SNatalie.Li@Sun.COM 	struct svcctl_GetServiceDisplayNameW *param = arg;
9297961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->manager_handle;
9307961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
9317961SNatalie.Li@Sun.COM 	svcctl_svc_node_t *svc;
9327961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
9337961SNatalie.Li@Sun.COM 
9347961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_MANAGER_CONTEXT);
9357961SNatalie.Li@Sun.COM 	if (hd == NULL) {
9367961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_GetServiceDisplayNameW));
9378334SJose.Borrego@Sun.COM 		param->display_name = NDR_STRDUP(mxa, "");
9387961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
9398334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
9407961SNatalie.Li@Sun.COM 	}
9417961SNatalie.Li@Sun.COM 
9427961SNatalie.Li@Sun.COM 	mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr;
9437961SNatalie.Li@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, (char *)param->service_name);
9447961SNatalie.Li@Sun.COM 	if (svc == NULL || svc->sn_fmri == NULL) {
9457961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_GetServiceDisplayNameW));
9468334SJose.Borrego@Sun.COM 		param->display_name = NDR_STRDUP(mxa, "");
9477961SNatalie.Li@Sun.COM 		param->status = ERROR_SERVICE_DOES_NOT_EXIST;
9488334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
9497961SNatalie.Li@Sun.COM 	}
9507961SNatalie.Li@Sun.COM 
9518334SJose.Borrego@Sun.COM 	param->display_name = NDR_STRDUP(mxa, svc->sn_fmri);
9527961SNatalie.Li@Sun.COM 	if (param->display_name == NULL) {
9537961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_GetServiceDisplayNameW));
9548334SJose.Borrego@Sun.COM 		param->display_name = NDR_STRDUP(mxa, "");
9557961SNatalie.Li@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
9568334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
9577961SNatalie.Li@Sun.COM 	}
9587961SNatalie.Li@Sun.COM 
9597961SNatalie.Li@Sun.COM 	param->buf_size = strlen(svc->sn_fmri);
9607961SNatalie.Li@Sun.COM 	param->status = ERROR_SUCCESS;
9618334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
9627961SNatalie.Li@Sun.COM }
9637961SNatalie.Li@Sun.COM 
9647961SNatalie.Li@Sun.COM /*
9657961SNatalie.Li@Sun.COM  * svcctl_s_GetServiceKeyNameW
9667961SNatalie.Li@Sun.COM  *
9677961SNatalie.Li@Sun.COM  * Returns:
9687961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
9697961SNatalie.Li@Sun.COM  *	ERROR_INVALID_HANDLE
9707961SNatalie.Li@Sun.COM  *	ERROR_SERVICE_DOES_NOT_EXIST
9717961SNatalie.Li@Sun.COM  */
9727961SNatalie.Li@Sun.COM static int
9738334SJose.Borrego@Sun.COM svcctl_s_GetServiceKeyNameW(void *arg, ndr_xa_t *mxa)
9747961SNatalie.Li@Sun.COM {
9757961SNatalie.Li@Sun.COM 	struct svcctl_GetServiceKeyNameW *param = arg;
9767961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->manager_handle;
9777961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
9787961SNatalie.Li@Sun.COM 	svcctl_svc_node_t *svc;
9797961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
9807961SNatalie.Li@Sun.COM 
9817961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_MANAGER_CONTEXT);
9827961SNatalie.Li@Sun.COM 	if (hd == NULL) {
9837961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_GetServiceKeyNameW));
9848334SJose.Borrego@Sun.COM 		param->key_name = NDR_STRDUP(mxa, "");
9857961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
9868334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
9877961SNatalie.Li@Sun.COM 	}
9887961SNatalie.Li@Sun.COM 
9897961SNatalie.Li@Sun.COM 	mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr;
9907961SNatalie.Li@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, (char *)param->service_name);
9917961SNatalie.Li@Sun.COM 	if (svc == NULL || svc->sn_name == NULL) {
9927961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_GetServiceKeyNameW));
9938334SJose.Borrego@Sun.COM 		param->key_name = NDR_STRDUP(mxa, "");
9947961SNatalie.Li@Sun.COM 		param->status = ERROR_SERVICE_DOES_NOT_EXIST;
9958334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
9967961SNatalie.Li@Sun.COM 	}
9977961SNatalie.Li@Sun.COM 
9988334SJose.Borrego@Sun.COM 	param->key_name = NDR_STRDUP(mxa, svc->sn_name);
9997961SNatalie.Li@Sun.COM 	if (param->key_name == NULL) {
10007961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_GetServiceKeyNameW));
10018334SJose.Borrego@Sun.COM 		param->key_name = NDR_STRDUP(mxa, "");
10027961SNatalie.Li@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
10038334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
10047961SNatalie.Li@Sun.COM 	}
10057961SNatalie.Li@Sun.COM 
10067961SNatalie.Li@Sun.COM 	param->buf_size = strlen(svc->sn_name);
10077961SNatalie.Li@Sun.COM 	param->status = ERROR_SUCCESS;
10088334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
10097961SNatalie.Li@Sun.COM }
10107961SNatalie.Li@Sun.COM 
10117961SNatalie.Li@Sun.COM /*
101210001SJoyce.McIntosh@Sun.COM  * svcctl_s_OpenSCManagerA
101310001SJoyce.McIntosh@Sun.COM  *
101410001SJoyce.McIntosh@Sun.COM  * Request to open the service control manager.
101510001SJoyce.McIntosh@Sun.COM  * The caller must have administrator rights in order to open this
101610001SJoyce.McIntosh@Sun.COM  * interface.  We don't support write (SC_MANAGER_LOCK) access.
101710001SJoyce.McIntosh@Sun.COM  *
101810001SJoyce.McIntosh@Sun.COM  * Returns:
101910001SJoyce.McIntosh@Sun.COM  *	ERROR_SUCCESS
102010001SJoyce.McIntosh@Sun.COM  *	ERROR_ACCESS_DENIED
102110001SJoyce.McIntosh@Sun.COM  *
102210001SJoyce.McIntosh@Sun.COM  * On success, returns a handle for use with subsequent svcctl requests.
102310001SJoyce.McIntosh@Sun.COM  */
102410001SJoyce.McIntosh@Sun.COM static int
102510001SJoyce.McIntosh@Sun.COM svcctl_s_OpenSCManagerA(void *arg, ndr_xa_t *mxa)
102610001SJoyce.McIntosh@Sun.COM {
102710001SJoyce.McIntosh@Sun.COM 	struct svcctl_OpenSCManagerA *param = arg;
102810001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = NULL;
102910001SJoyce.McIntosh@Sun.COM 	int rc;
103010001SJoyce.McIntosh@Sun.COM 
103110001SJoyce.McIntosh@Sun.COM 	rc = ndr_is_admin(mxa);
103210001SJoyce.McIntosh@Sun.COM 
103310001SJoyce.McIntosh@Sun.COM 	if ((rc == 0) || (param->desired_access & SC_MANAGER_LOCK) != 0) {
103410001SJoyce.McIntosh@Sun.COM 		bzero(&param->handle, sizeof (svcctl_handle_t));
103510001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
103610001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
103710001SJoyce.McIntosh@Sun.COM 	}
103810001SJoyce.McIntosh@Sun.COM 
103910001SJoyce.McIntosh@Sun.COM 	id = svcctl_mgr_hdalloc(mxa);
104010001SJoyce.McIntosh@Sun.COM 	if (id) {
104110001SJoyce.McIntosh@Sun.COM 		bcopy(id, &param->handle, sizeof (svcctl_handle_t));
104210001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_SUCCESS;
104310001SJoyce.McIntosh@Sun.COM 	} else {
104410001SJoyce.McIntosh@Sun.COM 		bzero(&param->handle, sizeof (svcctl_handle_t));
104510001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
104610001SJoyce.McIntosh@Sun.COM 	}
104710001SJoyce.McIntosh@Sun.COM 
104810001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
104910001SJoyce.McIntosh@Sun.COM }
105010001SJoyce.McIntosh@Sun.COM 
105110001SJoyce.McIntosh@Sun.COM /*
105210001SJoyce.McIntosh@Sun.COM  * svcctl_s_OpenServiceA
105310001SJoyce.McIntosh@Sun.COM  *
105410001SJoyce.McIntosh@Sun.COM  * Return a handle for use with subsequent svcctl requests.
105510001SJoyce.McIntosh@Sun.COM  *
105610001SJoyce.McIntosh@Sun.COM  * Returns:
105710001SJoyce.McIntosh@Sun.COM  *	ERROR_SUCCESS
105810001SJoyce.McIntosh@Sun.COM  *	ERROR_INVALID_HANDLE
105910001SJoyce.McIntosh@Sun.COM  *	ERROR_SERVICE_DOES_NOT_EXIST
106010001SJoyce.McIntosh@Sun.COM  *	ERROR_CALL_NOT_IMPLEMENTED
106110001SJoyce.McIntosh@Sun.COM  */
106210001SJoyce.McIntosh@Sun.COM static int
106310001SJoyce.McIntosh@Sun.COM svcctl_s_OpenServiceA(void *arg, ndr_xa_t *mxa)
106410001SJoyce.McIntosh@Sun.COM {
106510001SJoyce.McIntosh@Sun.COM 	struct svcctl_OpenServiceA *param = arg;
106610001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *mgrid = (ndr_hdid_t *)&param->manager_handle;
106710001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = NULL;
106810001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
106910001SJoyce.McIntosh@Sun.COM 	DWORD status;
107010001SJoyce.McIntosh@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
107110001SJoyce.McIntosh@Sun.COM 	char *svc_name = (char *)param->service_name->value;
107210001SJoyce.McIntosh@Sun.COM 	boolean_t unimplemented_operations = B_FALSE;
107310001SJoyce.McIntosh@Sun.COM 
107410001SJoyce.McIntosh@Sun.COM 	/* Allow service handle allocations for only status & config queries */
107510001SJoyce.McIntosh@Sun.COM 	unimplemented_operations =
107610001SJoyce.McIntosh@Sun.COM 	    SVCCTL_OPENSVC_OP_UNIMPLEMENTED(param->desired_access);
107710001SJoyce.McIntosh@Sun.COM 
107810001SJoyce.McIntosh@Sun.COM 	if (unimplemented_operations) {
107910001SJoyce.McIntosh@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
108010001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_CALL_NOT_IMPLEMENTED;
108110001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
108210001SJoyce.McIntosh@Sun.COM 	}
108310001SJoyce.McIntosh@Sun.COM 
108410001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, mgrid, SVCCTL_MANAGER_CONTEXT);
108510001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
108610001SJoyce.McIntosh@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
108710001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
108810001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
108910001SJoyce.McIntosh@Sun.COM 	}
109010001SJoyce.McIntosh@Sun.COM 
109110001SJoyce.McIntosh@Sun.COM 	mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr;
109210001SJoyce.McIntosh@Sun.COM 	status = svcctl_scm_validate_service(mgr_ctx, svc_name);
109310001SJoyce.McIntosh@Sun.COM 	if (status != ERROR_SUCCESS) {
109410001SJoyce.McIntosh@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
109510001SJoyce.McIntosh@Sun.COM 		param->status = status;
109610001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
109710001SJoyce.McIntosh@Sun.COM 	}
109810001SJoyce.McIntosh@Sun.COM 
109910001SJoyce.McIntosh@Sun.COM 	id = svcctl_svc_hdalloc(mxa, mgrid, svc_name);
110010001SJoyce.McIntosh@Sun.COM 	if (id) {
110110001SJoyce.McIntosh@Sun.COM 		bcopy(id, &param->service_handle, sizeof (svcctl_handle_t));
110210001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_SUCCESS;
110310001SJoyce.McIntosh@Sun.COM 	} else {
110410001SJoyce.McIntosh@Sun.COM 		bzero(&param->service_handle, sizeof (svcctl_handle_t));
110510001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
110610001SJoyce.McIntosh@Sun.COM 	}
110710001SJoyce.McIntosh@Sun.COM 
110810001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
110910001SJoyce.McIntosh@Sun.COM }
111010001SJoyce.McIntosh@Sun.COM 
111110001SJoyce.McIntosh@Sun.COM /*
111210001SJoyce.McIntosh@Sun.COM  * svcctl_s_EnumServicesStatusA
111310001SJoyce.McIntosh@Sun.COM  *
111410001SJoyce.McIntosh@Sun.COM  * Enumerate the list of services we support as ASCII.
111510001SJoyce.McIntosh@Sun.COM  */
111610001SJoyce.McIntosh@Sun.COM static int
111710001SJoyce.McIntosh@Sun.COM svcctl_s_EnumServicesStatusA(void *arg, ndr_xa_t *mxa)
111810001SJoyce.McIntosh@Sun.COM {
111910001SJoyce.McIntosh@Sun.COM 	struct svcctl_EnumServicesStatusA *param = arg;
112010001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->manager_handle;
112110001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
112210001SJoyce.McIntosh@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
112310001SJoyce.McIntosh@Sun.COM 	uint32_t buf_size;
112410001SJoyce.McIntosh@Sun.COM 	uint32_t svc_num;
112510001SJoyce.McIntosh@Sun.COM 	uint32_t resume_handle = 0;
112610001SJoyce.McIntosh@Sun.COM 	uint32_t status;
112710001SJoyce.McIntosh@Sun.COM 
112810001SJoyce.McIntosh@Sun.COM 	buf_size = param->buf_size;
112910001SJoyce.McIntosh@Sun.COM 	if (param->resume_handle != NULL)
113010001SJoyce.McIntosh@Sun.COM 		resume_handle = *param->resume_handle;
113110001SJoyce.McIntosh@Sun.COM 
113210001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_MANAGER_CONTEXT);
113310001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
113410001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
113510001SJoyce.McIntosh@Sun.COM 		goto enum_services_status_error;
113610001SJoyce.McIntosh@Sun.COM 	}
113710001SJoyce.McIntosh@Sun.COM 
113810001SJoyce.McIntosh@Sun.COM 	mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr;
113910001SJoyce.McIntosh@Sun.COM 	if (svcctl_scm_refresh(mgr_ctx) != 0) {
114010001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
114110001SJoyce.McIntosh@Sun.COM 		goto enum_services_status_error;
114210001SJoyce.McIntosh@Sun.COM 	}
114310001SJoyce.McIntosh@Sun.COM 
114410001SJoyce.McIntosh@Sun.COM 	param->services = NDR_MALLOC(mxa, buf_size);
114510001SJoyce.McIntosh@Sun.COM 	if (param->services == NULL) {
114610001SJoyce.McIntosh@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
114710001SJoyce.McIntosh@Sun.COM 		goto enum_services_status_error;
114810001SJoyce.McIntosh@Sun.COM 	}
114910001SJoyce.McIntosh@Sun.COM 	bzero(param->services, buf_size);
115010001SJoyce.McIntosh@Sun.COM 
115110001SJoyce.McIntosh@Sun.COM 	svc_num = svcctl_scm_enum_services(mgr_ctx, param->services,
115210001SJoyce.McIntosh@Sun.COM 	    buf_size, &resume_handle, B_FALSE);
115310001SJoyce.McIntosh@Sun.COM 
115410001SJoyce.McIntosh@Sun.COM 	param->buf_size = buf_size;
115510001SJoyce.McIntosh@Sun.COM 	param->svc_num = svc_num;
115610001SJoyce.McIntosh@Sun.COM 
115710001SJoyce.McIntosh@Sun.COM 	if (resume_handle != 0) {
115810001SJoyce.McIntosh@Sun.COM 		if (param->resume_handle != NULL)
115910001SJoyce.McIntosh@Sun.COM 			*param->resume_handle = resume_handle;
116010001SJoyce.McIntosh@Sun.COM 		param->bytes_needed = mgr_ctx->mc_bytes_needed;
116110001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_MORE_DATA;
116210001SJoyce.McIntosh@Sun.COM 	} else {
116310001SJoyce.McIntosh@Sun.COM 		if (param->resume_handle)
116410001SJoyce.McIntosh@Sun.COM 			*param->resume_handle = 0;
116510001SJoyce.McIntosh@Sun.COM 		param->bytes_needed = 0;
116610001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_SUCCESS;
116710001SJoyce.McIntosh@Sun.COM 	}
116810001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
116910001SJoyce.McIntosh@Sun.COM 
117010001SJoyce.McIntosh@Sun.COM enum_services_status_error:
117110001SJoyce.McIntosh@Sun.COM 	bzero(param, sizeof (struct svcctl_EnumServicesStatusA));
117210001SJoyce.McIntosh@Sun.COM 	param->services = NDR_STRDUP(mxa, "");
117310001SJoyce.McIntosh@Sun.COM 	param->status = status;
117410001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
117510001SJoyce.McIntosh@Sun.COM }
117610001SJoyce.McIntosh@Sun.COM 
117710001SJoyce.McIntosh@Sun.COM /*
11787961SNatalie.Li@Sun.COM  * svcctl_s_QueryServiceConfig2W
11797961SNatalie.Li@Sun.COM  *
11807961SNatalie.Li@Sun.COM  * Returns:
11817961SNatalie.Li@Sun.COM  *	ERROR_SUCCESS
11827961SNatalie.Li@Sun.COM  *	ERROR_INVALID_HANDLE
11837961SNatalie.Li@Sun.COM  *	ERROR_INVALID_LEVEL
11847961SNatalie.Li@Sun.COM  *	ERROR_NOT_ENOUGH_MEMORY
11857961SNatalie.Li@Sun.COM  */
11867961SNatalie.Li@Sun.COM static int
11878334SJose.Borrego@Sun.COM svcctl_s_QueryServiceConfig2W(void *arg, ndr_xa_t *mxa)
11887961SNatalie.Li@Sun.COM {
11897961SNatalie.Li@Sun.COM 	struct svcctl_QueryServiceConfig2W *param = arg;
11907961SNatalie.Li@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
11917961SNatalie.Li@Sun.COM 	ndr_handle_t *hd;
11927961SNatalie.Li@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
11937961SNatalie.Li@Sun.COM 	svcctl_service_context_t *svc_ctx;
11947961SNatalie.Li@Sun.COM 	svcctl_svc_node_t *svc;
119510504SKeyur.Desai@Sun.COM 	svc_config_rsp_t svc_rsp;
11967961SNatalie.Li@Sun.COM 	int offset, input_bufsize, bytes_needed = 0;
1197*10966SJordan.Brown@Sun.COM 	smb_wchar_t *wide_desc;
11987961SNatalie.Li@Sun.COM 	char *desc;
11997961SNatalie.Li@Sun.COM 	DWORD status;
12007961SNatalie.Li@Sun.COM 
12017961SNatalie.Li@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
12027961SNatalie.Li@Sun.COM 	if (hd == NULL) {
12037961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceConfig2W));
12048334SJose.Borrego@Sun.COM 		param->buffer = NDR_STRDUP(mxa, "");
12057961SNatalie.Li@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
12068334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
12077961SNatalie.Li@Sun.COM 	}
12087961SNatalie.Li@Sun.COM 
12097961SNatalie.Li@Sun.COM 	input_bufsize = param->buf_size;
12108334SJose.Borrego@Sun.COM 	param->buffer = NDR_MALLOC(mxa, input_bufsize);
12117961SNatalie.Li@Sun.COM 	if (param->buffer == NULL) {
12127961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceConfig2W));
12138334SJose.Borrego@Sun.COM 		param->buffer = NDR_STRDUP(mxa, "");
12147961SNatalie.Li@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
12158334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
12167961SNatalie.Li@Sun.COM 	}
12177961SNatalie.Li@Sun.COM 	bzero(param->buffer, input_bufsize);
12187961SNatalie.Li@Sun.COM 
121910504SKeyur.Desai@Sun.COM 	svc_rsp.svc_buf = param->buffer;
12207961SNatalie.Li@Sun.COM 	status = ERROR_SUCCESS;
12217961SNatalie.Li@Sun.COM 	switch (param->info_level) {
12227961SNatalie.Li@Sun.COM 	case SERVICE_CONFIG_DESCRIPTION:
12237961SNatalie.Li@Sun.COM 		svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc;
12247961SNatalie.Li@Sun.COM 		mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid);
12257961SNatalie.Li@Sun.COM 		if (mgr_ctx == NULL) {
12267961SNatalie.Li@Sun.COM 			param->status = ERROR_INVALID_HANDLE;
12277961SNatalie.Li@Sun.COM 			break;
12287961SNatalie.Li@Sun.COM 		}
12297961SNatalie.Li@Sun.COM 
12307961SNatalie.Li@Sun.COM 		svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname);
12317961SNatalie.Li@Sun.COM 		if (svc == NULL || svc->sn_desc == NULL) {
12327961SNatalie.Li@Sun.COM 			status = ERROR_SERVICE_DOES_NOT_EXIST;
12337961SNatalie.Li@Sun.COM 			break;
12347961SNatalie.Li@Sun.COM 		}
12357961SNatalie.Li@Sun.COM 
12367961SNatalie.Li@Sun.COM 		desc = svc->sn_desc;
12377961SNatalie.Li@Sun.COM 		bytes_needed = SVCCTL_WNSTRLEN(desc);
12387961SNatalie.Li@Sun.COM 
12397961SNatalie.Li@Sun.COM 		if (input_bufsize <= bytes_needed) {
12407961SNatalie.Li@Sun.COM 			param->bytes_needed = bytes_needed;
124110001SJoyce.McIntosh@Sun.COM 			param->status = ERROR_INSUFFICIENT_BUFFER;
12428334SJose.Borrego@Sun.COM 			return (NDR_DRC_OK);
12437961SNatalie.Li@Sun.COM 		}
12447961SNatalie.Li@Sun.COM 
12457961SNatalie.Li@Sun.COM 		offset = sizeof (svc_description_t);
124610504SKeyur.Desai@Sun.COM 		svc_rsp.svc_desc->desc = offset;
12477961SNatalie.Li@Sun.COM 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
1248*10966SJordan.Brown@Sun.COM 		wide_desc = (smb_wchar_t *)&param->buffer[offset];
1249*10966SJordan.Brown@Sun.COM 		(void) smb_mbstowcs(wide_desc, desc, (strlen(desc) + 1));
125010504SKeyur.Desai@Sun.COM 		offset += SVCCTL_WNSTRLEN(desc);
12517961SNatalie.Li@Sun.COM 
12527961SNatalie.Li@Sun.COM 		param->bytes_needed = offset;
12537961SNatalie.Li@Sun.COM 		break;
12547961SNatalie.Li@Sun.COM 
12557961SNatalie.Li@Sun.COM 	case SERVICE_CONFIG_FAILURE_ACTIONS:
125610504SKeyur.Desai@Sun.COM 		bzero(svc_rsp.svc_fac, sizeof (svc_failure_actions_t));
125710504SKeyur.Desai@Sun.COM 		bytes_needed = sizeof (svc_failure_actions_t);
125810504SKeyur.Desai@Sun.COM 		if (input_bufsize <= bytes_needed) {
125910504SKeyur.Desai@Sun.COM 			param->bytes_needed = bytes_needed;
126010504SKeyur.Desai@Sun.COM 			param->status = ERROR_INSUFFICIENT_BUFFER;
126110504SKeyur.Desai@Sun.COM 			return (NDR_DRC_OK);
126210504SKeyur.Desai@Sun.COM 		}
126310504SKeyur.Desai@Sun.COM 		param->bytes_needed = bytes_needed;
12647961SNatalie.Li@Sun.COM 		break;
12657961SNatalie.Li@Sun.COM 
126610504SKeyur.Desai@Sun.COM 	case SERVICE_CONFIG_DELAYED_AUTO_START_INFO:
126710504SKeyur.Desai@Sun.COM 		svc_rsp.svc_dstart->dstart = 0;
126810504SKeyur.Desai@Sun.COM 		param->bytes_needed = sizeof (svc_delayed_auto_start_t);
126910504SKeyur.Desai@Sun.COM 		break;
127010504SKeyur.Desai@Sun.COM 
127110504SKeyur.Desai@Sun.COM 	case SERVICE_CONFIG_FAILURE_ACTIONS_FLAG:
127210504SKeyur.Desai@Sun.COM 		svc_rsp.svc_cfa->cfa = 0;
127310504SKeyur.Desai@Sun.COM 		param->bytes_needed = sizeof (svc_config_failure_action_t);
127410504SKeyur.Desai@Sun.COM 		break;
127510504SKeyur.Desai@Sun.COM 
127610504SKeyur.Desai@Sun.COM 	case SERVICE_CONFIG_SERVICE_SID_INFO:
127710504SKeyur.Desai@Sun.COM 	case SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO:
127810504SKeyur.Desai@Sun.COM 	case SERVICE_CONFIG_PRESHUTDOWN_INFO:
127910504SKeyur.Desai@Sun.COM 	case SERVICE_CONFIG_TRIGGER_INFO:
128010504SKeyur.Desai@Sun.COM 	case SERVICE_CONFIG_PREFERRED_NODE:
12817961SNatalie.Li@Sun.COM 	default:
12827961SNatalie.Li@Sun.COM 		status = ERROR_INVALID_LEVEL;
12837961SNatalie.Li@Sun.COM 		break;
12847961SNatalie.Li@Sun.COM 	}
12857961SNatalie.Li@Sun.COM 
12867961SNatalie.Li@Sun.COM 	if (status != ERROR_SUCCESS) {
12877961SNatalie.Li@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceConfig2W));
12888334SJose.Borrego@Sun.COM 		param->buffer = NDR_STRDUP(mxa, "");
12897961SNatalie.Li@Sun.COM 		param->status = status;
12908334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
12917961SNatalie.Li@Sun.COM 	}
12927961SNatalie.Li@Sun.COM 
12937961SNatalie.Li@Sun.COM 	param->status = ERROR_SUCCESS;
12948334SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
12957961SNatalie.Li@Sun.COM }
129610001SJoyce.McIntosh@Sun.COM 
129710001SJoyce.McIntosh@Sun.COM /*
129810001SJoyce.McIntosh@Sun.COM  * svcctl_s_QueryServiceStatusEx
129910001SJoyce.McIntosh@Sun.COM  */
130010001SJoyce.McIntosh@Sun.COM static int
130110001SJoyce.McIntosh@Sun.COM svcctl_s_QueryServiceStatusEx(void *arg, ndr_xa_t *mxa)
130210001SJoyce.McIntosh@Sun.COM {
130310001SJoyce.McIntosh@Sun.COM 	struct svcctl_QueryServiceStatusEx *param = arg;
130410001SJoyce.McIntosh@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->service_handle;
130510001SJoyce.McIntosh@Sun.COM 	ndr_handle_t *hd;
130610001SJoyce.McIntosh@Sun.COM 	svcctl_manager_context_t *mgr_ctx;
130710001SJoyce.McIntosh@Sun.COM 	svcctl_service_context_t *svc_ctx;
130810001SJoyce.McIntosh@Sun.COM 	svcctl_svc_node_t *svc;
130910001SJoyce.McIntosh@Sun.COM 	svc_status_ex_t *svc_status_ex;
131010001SJoyce.McIntosh@Sun.COM 	uint32_t input_bufsize;
131110001SJoyce.McIntosh@Sun.COM 	uint32_t bytes_needed;
131210001SJoyce.McIntosh@Sun.COM 	DWORD status;
131310001SJoyce.McIntosh@Sun.COM 
131410001SJoyce.McIntosh@Sun.COM 	hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT);
131510001SJoyce.McIntosh@Sun.COM 	if (hd == NULL) {
131610001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
131710001SJoyce.McIntosh@Sun.COM 		goto query_service_status_ex_error;
131810001SJoyce.McIntosh@Sun.COM 	}
131910001SJoyce.McIntosh@Sun.COM 
132010001SJoyce.McIntosh@Sun.COM 	svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc;
132110001SJoyce.McIntosh@Sun.COM 	mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid);
132210001SJoyce.McIntosh@Sun.COM 	if (mgr_ctx == NULL) {
132310001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_HANDLE;
132410001SJoyce.McIntosh@Sun.COM 		goto query_service_status_ex_error;
132510001SJoyce.McIntosh@Sun.COM 	}
132610001SJoyce.McIntosh@Sun.COM 
132710001SJoyce.McIntosh@Sun.COM 	if (param->info_level != SC_STATUS_PROCESS_INFO) {
132810001SJoyce.McIntosh@Sun.COM 		status = ERROR_INVALID_PARAMETER;
132910001SJoyce.McIntosh@Sun.COM 		goto query_service_status_ex_error;
133010001SJoyce.McIntosh@Sun.COM 	}
133110001SJoyce.McIntosh@Sun.COM 
133210504SKeyur.Desai@Sun.COM 	bytes_needed = sizeof (svc_status_ex_t);
133310001SJoyce.McIntosh@Sun.COM 
133410001SJoyce.McIntosh@Sun.COM 	if ((input_bufsize = param->buf_size) < bytes_needed) {
133510001SJoyce.McIntosh@Sun.COM 		bzero(param, sizeof (struct svcctl_QueryServiceStatusEx));
133610001SJoyce.McIntosh@Sun.COM 		param->buf_size = input_bufsize;
133710001SJoyce.McIntosh@Sun.COM 		param->buffer = NDR_STRDUP(mxa, "");
133810001SJoyce.McIntosh@Sun.COM 		param->bytes_needed = bytes_needed;
133910001SJoyce.McIntosh@Sun.COM 		param->status = ERROR_INSUFFICIENT_BUFFER;
134010001SJoyce.McIntosh@Sun.COM 		return (NDR_DRC_OK);
134110001SJoyce.McIntosh@Sun.COM 	}
134210001SJoyce.McIntosh@Sun.COM 
134310001SJoyce.McIntosh@Sun.COM 	if ((svc_status_ex = NDR_MALLOC(mxa, bytes_needed)) == NULL) {
134410001SJoyce.McIntosh@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
134510001SJoyce.McIntosh@Sun.COM 		goto query_service_status_ex_error;
134610001SJoyce.McIntosh@Sun.COM 	}
134710001SJoyce.McIntosh@Sun.COM 
134810001SJoyce.McIntosh@Sun.COM 	svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname);
134910001SJoyce.McIntosh@Sun.COM 	if (svc == NULL || svc->sn_state == NULL) {
135010001SJoyce.McIntosh@Sun.COM 		status = ERROR_SERVICE_DOES_NOT_EXIST;
135110001SJoyce.McIntosh@Sun.COM 		goto query_service_status_ex_error;
135210001SJoyce.McIntosh@Sun.COM 	}
135310001SJoyce.McIntosh@Sun.COM 
135410001SJoyce.McIntosh@Sun.COM 	svc_status_ex->service_type = SERVICE_WIN32_SHARE_PROCESS;
135510001SJoyce.McIntosh@Sun.COM 	svc_status_ex->cur_state = svcctl_scm_map_status(svc->sn_state);
135610001SJoyce.McIntosh@Sun.COM 	svc_status_ex->ctrl_accepted = 0;
135710001SJoyce.McIntosh@Sun.COM 	svc_status_ex->w32_exitcode = 0;
135810001SJoyce.McIntosh@Sun.COM 	svc_status_ex->svc_specified_exitcode = 0;
135910001SJoyce.McIntosh@Sun.COM 	svc_status_ex->check_point = 0;
136010001SJoyce.McIntosh@Sun.COM 	svc_status_ex->wait_hint = 0;
136110001SJoyce.McIntosh@Sun.COM 	svc_status_ex->process_id = 1;
136210001SJoyce.McIntosh@Sun.COM 	svc_status_ex->service_flags = 1;
136310001SJoyce.McIntosh@Sun.COM 
136410001SJoyce.McIntosh@Sun.COM 	param->buffer = (uint8_t *)svc_status_ex;
136510504SKeyur.Desai@Sun.COM 	param->buf_size = input_bufsize;
136610504SKeyur.Desai@Sun.COM 	param->bytes_needed = bytes_needed;
136710001SJoyce.McIntosh@Sun.COM 	param->status = ERROR_SUCCESS;
136810001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
136910001SJoyce.McIntosh@Sun.COM 
137010001SJoyce.McIntosh@Sun.COM query_service_status_ex_error:
137110001SJoyce.McIntosh@Sun.COM 	bzero(param, sizeof (struct svcctl_QueryServiceStatusEx));
137210001SJoyce.McIntosh@Sun.COM 	param->buffer = NDR_STRDUP(mxa, "");
137310001SJoyce.McIntosh@Sun.COM 	param->status = status;
137410001SJoyce.McIntosh@Sun.COM 	return (NDR_DRC_OK);
137510001SJoyce.McIntosh@Sun.COM }
1376