xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/winreg_svc.c (revision 11447:b5b2a9bd508f)
18474SJose.Borrego@Sun.COM /*
28474SJose.Borrego@Sun.COM  * CDDL HEADER START
38474SJose.Borrego@Sun.COM  *
48474SJose.Borrego@Sun.COM  * The contents of this file are subject to the terms of the
58474SJose.Borrego@Sun.COM  * Common Development and Distribution License (the "License").
68474SJose.Borrego@Sun.COM  * You may not use this file except in compliance with the License.
78474SJose.Borrego@Sun.COM  *
88474SJose.Borrego@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98474SJose.Borrego@Sun.COM  * or http://www.opensolaris.org/os/licensing.
108474SJose.Borrego@Sun.COM  * See the License for the specific language governing permissions
118474SJose.Borrego@Sun.COM  * and limitations under the License.
128474SJose.Borrego@Sun.COM  *
138474SJose.Borrego@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
148474SJose.Borrego@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158474SJose.Borrego@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
168474SJose.Borrego@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
178474SJose.Borrego@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
188474SJose.Borrego@Sun.COM  *
198474SJose.Borrego@Sun.COM  * CDDL HEADER END
208474SJose.Borrego@Sun.COM  */
218474SJose.Borrego@Sun.COM /*
22*11447Samw@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
238474SJose.Borrego@Sun.COM  * Use is subject to license terms.
248474SJose.Borrego@Sun.COM  */
258474SJose.Borrego@Sun.COM 
268474SJose.Borrego@Sun.COM /*
278474SJose.Borrego@Sun.COM  * Windows Registry RPC (WINREG) server-side interface.
288474SJose.Borrego@Sun.COM  *
298670SJose.Borrego@Sun.COM  * The registry is a database with a hierarchical structure similar to
308670SJose.Borrego@Sun.COM  * a file system, with keys in place of directories and values in place
318670SJose.Borrego@Sun.COM  * of files.  The top level keys are known as root keys and each key can
328670SJose.Borrego@Sun.COM  * contain subkeys and values.  As with directories and sub-directories,
338670SJose.Borrego@Sun.COM  * the terms key and subkey are used interchangeably.  Values, analogous
348670SJose.Borrego@Sun.COM  * to files, contain data.
358474SJose.Borrego@Sun.COM  *
368670SJose.Borrego@Sun.COM  * A specific subkey can be identifies by its fully qualified name (FQN),
378670SJose.Borrego@Sun.COM  * which is analogous to a file system path.  In the registry, the key
388670SJose.Borrego@Sun.COM  * separator is the '\' character, which is reserved and cannot appear
398670SJose.Borrego@Sun.COM  * in key or value names.  Registry names are case-insensitive.
408670SJose.Borrego@Sun.COM  *
418670SJose.Borrego@Sun.COM  * For example:  HKEY_LOCAL_MACHINE\System\CurrentControlSet
428670SJose.Borrego@Sun.COM  *
439914Samw@Sun.COM  * The HKEY_LOCAL_MACHINE root key contains a subkey called System, and
448670SJose.Borrego@Sun.COM  * System contains a subkey called CurrentControlSet.
458670SJose.Borrego@Sun.COM  *
468670SJose.Borrego@Sun.COM  * The WINREG RPC interface returns Win32 error codes.
478474SJose.Borrego@Sun.COM  */
488474SJose.Borrego@Sun.COM 
498474SJose.Borrego@Sun.COM #include <sys/utsname.h>
508474SJose.Borrego@Sun.COM #include <strings.h>
518474SJose.Borrego@Sun.COM 
528474SJose.Borrego@Sun.COM #include <smbsrv/libsmb.h>
538474SJose.Borrego@Sun.COM #include <smbsrv/ntstatus.h>
548474SJose.Borrego@Sun.COM #include <smbsrv/nterror.h>
558474SJose.Borrego@Sun.COM #include <smbsrv/nmpipes.h>
568474SJose.Borrego@Sun.COM #include <smbsrv/libmlsvc.h>
578474SJose.Borrego@Sun.COM #include <smbsrv/ndl/winreg.ndl>
588474SJose.Borrego@Sun.COM 
598474SJose.Borrego@Sun.COM /*
608474SJose.Borrego@Sun.COM  * List of supported registry keys (case-insensitive).
618474SJose.Borrego@Sun.COM  */
628474SJose.Borrego@Sun.COM static char *winreg_keys[] = {
639914Samw@Sun.COM 	"HKLM",
649914Samw@Sun.COM 	"HKU",
659914Samw@Sun.COM 	"HKLM\\SOFTWARE",
669914Samw@Sun.COM 	"HKLM\\SYSTEM",
6710504SKeyur.Desai@Sun.COM 	"Application",
6810504SKeyur.Desai@Sun.COM 	"Security",
699914Samw@Sun.COM 	"System",
709914Samw@Sun.COM 	"CurrentControlSet",
718474SJose.Borrego@Sun.COM 	"System\\CurrentControlSet\\Services\\Eventlog",
728670SJose.Borrego@Sun.COM 	"System\\CurrentControlSet\\Services\\Eventlog\\Application",
738670SJose.Borrego@Sun.COM 	"System\\CurrentControlSet\\Services\\Eventlog\\Security",
748474SJose.Borrego@Sun.COM 	"System\\CurrentControlSet\\Services\\Eventlog\\System",
758474SJose.Borrego@Sun.COM 	"System\\CurrentControlSet\\Control\\ProductOptions",
769914Samw@Sun.COM 	"SOFTWARE",
778474SJose.Borrego@Sun.COM 	"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
788474SJose.Borrego@Sun.COM };
798474SJose.Borrego@Sun.COM 
808474SJose.Borrego@Sun.COM typedef struct winreg_subkey {
818474SJose.Borrego@Sun.COM 	list_node_t sk_lnd;
828474SJose.Borrego@Sun.COM 	ndr_hdid_t sk_handle;
838474SJose.Borrego@Sun.COM 	char sk_name[MAXPATHLEN];
848474SJose.Borrego@Sun.COM 	boolean_t sk_predefined;
858474SJose.Borrego@Sun.COM } winreg_subkey_t;
868474SJose.Borrego@Sun.COM 
878474SJose.Borrego@Sun.COM typedef struct winreg_keylist {
888474SJose.Borrego@Sun.COM 	list_t kl_list;
898474SJose.Borrego@Sun.COM 	int kl_count;
908474SJose.Borrego@Sun.COM } winreg_keylist_t;
918474SJose.Borrego@Sun.COM 
928474SJose.Borrego@Sun.COM static winreg_keylist_t winreg_keylist;
938474SJose.Borrego@Sun.COM 
948474SJose.Borrego@Sun.COM static boolean_t winreg_key_has_subkey(const char *);
958670SJose.Borrego@Sun.COM static char *winreg_enum_subkey(ndr_xa_t *, const char *, uint32_t);
968474SJose.Borrego@Sun.COM static char *winreg_lookup_value(const char *);
97*11447Samw@Sun.COM static uint32_t winreg_sd_format(smb_sd_t *);
98*11447Samw@Sun.COM uint32_t srvsvc_sd_set_relative(smb_sd_t *, uint8_t *);
998474SJose.Borrego@Sun.COM 
1008670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCR(void *, ndr_xa_t *);
1018670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCU(void *, ndr_xa_t *);
1028474SJose.Borrego@Sun.COM static int winreg_s_OpenHKLM(void *, ndr_xa_t *);
1038670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPD(void *, ndr_xa_t *);
1048670SJose.Borrego@Sun.COM static int winreg_s_OpenHKU(void *, ndr_xa_t *);
1058670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCC(void *, ndr_xa_t *);
1068670SJose.Borrego@Sun.COM static int winreg_s_OpenHKDD(void *, ndr_xa_t *);
1078670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPT(void *, ndr_xa_t *);
1088670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPN(void *, ndr_xa_t *);
1098670SJose.Borrego@Sun.COM static int winreg_s_OpenHK(void *, ndr_xa_t *, const char *);
1108474SJose.Borrego@Sun.COM static int winreg_s_Close(void *, ndr_xa_t *);
1118474SJose.Borrego@Sun.COM static int winreg_s_CreateKey(void *, ndr_xa_t *);
1128474SJose.Borrego@Sun.COM static int winreg_s_DeleteKey(void *, ndr_xa_t *);
1138474SJose.Borrego@Sun.COM static int winreg_s_DeleteValue(void *, ndr_xa_t *);
1148474SJose.Borrego@Sun.COM static int winreg_s_EnumKey(void *, ndr_xa_t *);
1158474SJose.Borrego@Sun.COM static int winreg_s_EnumValue(void *, ndr_xa_t *);
1168474SJose.Borrego@Sun.COM static int winreg_s_FlushKey(void *, ndr_xa_t *);
1178474SJose.Borrego@Sun.COM static int winreg_s_GetKeySec(void *, ndr_xa_t *);
1188474SJose.Borrego@Sun.COM static int winreg_s_NotifyChange(void *, ndr_xa_t *);
1198474SJose.Borrego@Sun.COM static int winreg_s_OpenKey(void *, ndr_xa_t *);
1208474SJose.Borrego@Sun.COM static int winreg_s_QueryKey(void *, ndr_xa_t *);
1218474SJose.Borrego@Sun.COM static int winreg_s_QueryValue(void *, ndr_xa_t *);
1228474SJose.Borrego@Sun.COM static int winreg_s_SetKeySec(void *, ndr_xa_t *);
1238474SJose.Borrego@Sun.COM static int winreg_s_CreateValue(void *, ndr_xa_t *);
1248474SJose.Borrego@Sun.COM static int winreg_s_Shutdown(void *, ndr_xa_t *);
1258474SJose.Borrego@Sun.COM static int winreg_s_AbortShutdown(void *, ndr_xa_t *);
1268474SJose.Borrego@Sun.COM static int winreg_s_GetVersion(void *, ndr_xa_t *);
1278474SJose.Borrego@Sun.COM 
1288474SJose.Borrego@Sun.COM static ndr_stub_table_t winreg_stub_table[] = {
1298670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKCR,	WINREG_OPNUM_OpenHKCR },
1308670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKCU,	WINREG_OPNUM_OpenHKCU },
1318474SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKLM,	WINREG_OPNUM_OpenHKLM },
1328670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKPD,	WINREG_OPNUM_OpenHKPD },
1338670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKU,	WINREG_OPNUM_OpenHKUsers },
1348474SJose.Borrego@Sun.COM 	{ winreg_s_Close,	WINREG_OPNUM_Close },
1358474SJose.Borrego@Sun.COM 	{ winreg_s_CreateKey,	WINREG_OPNUM_CreateKey },
1368474SJose.Borrego@Sun.COM 	{ winreg_s_DeleteKey,	WINREG_OPNUM_DeleteKey },
1378474SJose.Borrego@Sun.COM 	{ winreg_s_DeleteValue,	WINREG_OPNUM_DeleteValue },
1388474SJose.Borrego@Sun.COM 	{ winreg_s_EnumKey,	WINREG_OPNUM_EnumKey },
1398474SJose.Borrego@Sun.COM 	{ winreg_s_EnumValue,	WINREG_OPNUM_EnumValue },
1408474SJose.Borrego@Sun.COM 	{ winreg_s_FlushKey,	WINREG_OPNUM_FlushKey },
1418474SJose.Borrego@Sun.COM 	{ winreg_s_GetKeySec,	WINREG_OPNUM_GetKeySec },
1428474SJose.Borrego@Sun.COM 	{ winreg_s_NotifyChange,	WINREG_OPNUM_NotifyChange },
1438474SJose.Borrego@Sun.COM 	{ winreg_s_OpenKey,	WINREG_OPNUM_OpenKey },
1448474SJose.Borrego@Sun.COM 	{ winreg_s_QueryKey,	WINREG_OPNUM_QueryKey },
1458474SJose.Borrego@Sun.COM 	{ winreg_s_QueryValue,	WINREG_OPNUM_QueryValue },
1468474SJose.Borrego@Sun.COM 	{ winreg_s_SetKeySec,	WINREG_OPNUM_SetKeySec },
1478474SJose.Borrego@Sun.COM 	{ winreg_s_CreateValue,	WINREG_OPNUM_CreateValue },
1488474SJose.Borrego@Sun.COM 	{ winreg_s_Shutdown,	WINREG_OPNUM_Shutdown },
1498474SJose.Borrego@Sun.COM 	{ winreg_s_AbortShutdown,	WINREG_OPNUM_AbortShutdown },
1508474SJose.Borrego@Sun.COM 	{ winreg_s_GetVersion,	WINREG_OPNUM_GetVersion },
1518670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKCC,	WINREG_OPNUM_OpenHKCC },
1528670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKDD,	WINREG_OPNUM_OpenHKDD },
1538670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKPT,	WINREG_OPNUM_OpenHKPT },
1548670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKPN,	WINREG_OPNUM_OpenHKPN },
1558474SJose.Borrego@Sun.COM 	{0}
1568474SJose.Borrego@Sun.COM };
1578474SJose.Borrego@Sun.COM 
1588474SJose.Borrego@Sun.COM static ndr_service_t winreg_service = {
1598474SJose.Borrego@Sun.COM 	"Winreg",			/* name */
1608474SJose.Borrego@Sun.COM 	"Windows Registry",		/* desc */
1618474SJose.Borrego@Sun.COM 	"\\winreg",			/* endpoint */
1628474SJose.Borrego@Sun.COM 	PIPE_WINREG,			/* sec_addr_port */
1638474SJose.Borrego@Sun.COM 	"338cd001-2244-31f1-aaaa-900038001003", 1,	/* abstract */
1648474SJose.Borrego@Sun.COM 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
1658474SJose.Borrego@Sun.COM 	0,				/* no bind_instance_size */
1668474SJose.Borrego@Sun.COM 	0,				/* no bind_req() */
1678474SJose.Borrego@Sun.COM 	0,				/* no unbind_and_close() */
1688474SJose.Borrego@Sun.COM 	0,				/* use generic_call_stub() */
1698474SJose.Borrego@Sun.COM 	&TYPEINFO(winreg_interface),	/* interface ti */
1708474SJose.Borrego@Sun.COM 	winreg_stub_table		/* stub_table */
1718474SJose.Borrego@Sun.COM };
1728474SJose.Borrego@Sun.COM 
1738474SJose.Borrego@Sun.COM static char winreg_sysname[SYS_NMLN];
1748474SJose.Borrego@Sun.COM 
1758474SJose.Borrego@Sun.COM /*
1768474SJose.Borrego@Sun.COM  * winreg_initialize
1778474SJose.Borrego@Sun.COM  *
1788474SJose.Borrego@Sun.COM  * Initialize and register the WINREG RPC interface with the RPC runtime
1798474SJose.Borrego@Sun.COM  * library. It must be called in order to use either the client side
1808474SJose.Borrego@Sun.COM  * or the server side functions.
1818474SJose.Borrego@Sun.COM  */
1828474SJose.Borrego@Sun.COM void
1838474SJose.Borrego@Sun.COM winreg_initialize(void)
1848474SJose.Borrego@Sun.COM {
1858474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
1868474SJose.Borrego@Sun.COM 	struct utsname name;
1878474SJose.Borrego@Sun.COM 	char *sysname;
1888474SJose.Borrego@Sun.COM 	int i;
1898474SJose.Borrego@Sun.COM 
1908474SJose.Borrego@Sun.COM 	list_create(&winreg_keylist.kl_list, sizeof (winreg_subkey_t),
1918474SJose.Borrego@Sun.COM 	    offsetof(winreg_subkey_t, sk_lnd));
1928474SJose.Borrego@Sun.COM 	winreg_keylist.kl_count = 0;
1938474SJose.Borrego@Sun.COM 
1948474SJose.Borrego@Sun.COM 	for (i = 0; i < sizeof (winreg_keys)/sizeof (winreg_keys[0]); ++i) {
1958474SJose.Borrego@Sun.COM 		if ((key = malloc(sizeof (winreg_subkey_t))) != NULL) {
1968474SJose.Borrego@Sun.COM 			bzero(key, sizeof (winreg_subkey_t));
1978474SJose.Borrego@Sun.COM 			(void) strlcpy(key->sk_name, winreg_keys[i],
1988474SJose.Borrego@Sun.COM 			    MAXPATHLEN);
1998474SJose.Borrego@Sun.COM 			key->sk_predefined = B_TRUE;
2008474SJose.Borrego@Sun.COM 			list_insert_tail(&winreg_keylist.kl_list, key);
2018474SJose.Borrego@Sun.COM 			++winreg_keylist.kl_count;
2028474SJose.Borrego@Sun.COM 		}
2038474SJose.Borrego@Sun.COM 	}
2048474SJose.Borrego@Sun.COM 
2058474SJose.Borrego@Sun.COM 	if (uname(&name) < 0)
2068474SJose.Borrego@Sun.COM 		sysname = "Solaris";
2078474SJose.Borrego@Sun.COM 	else
2088474SJose.Borrego@Sun.COM 		sysname = name.sysname;
2098474SJose.Borrego@Sun.COM 
2108474SJose.Borrego@Sun.COM 	(void) strlcpy(winreg_sysname, sysname, SYS_NMLN);
2118474SJose.Borrego@Sun.COM 	(void) ndr_svc_register(&winreg_service);
2128474SJose.Borrego@Sun.COM }
2138474SJose.Borrego@Sun.COM 
2148670SJose.Borrego@Sun.COM static int
2158670SJose.Borrego@Sun.COM winreg_s_OpenHKCR(void *arg, ndr_xa_t *mxa)
2168670SJose.Borrego@Sun.COM {
2178670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKCR"));
2188670SJose.Borrego@Sun.COM }
2198670SJose.Borrego@Sun.COM 
2208474SJose.Borrego@Sun.COM static int
2218670SJose.Borrego@Sun.COM winreg_s_OpenHKCU(void *arg, ndr_xa_t *mxa)
2228670SJose.Borrego@Sun.COM {
2238670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKCU"));
2248670SJose.Borrego@Sun.COM }
2258670SJose.Borrego@Sun.COM 
2268670SJose.Borrego@Sun.COM static int
2278670SJose.Borrego@Sun.COM winreg_s_OpenHKLM(void *arg, ndr_xa_t *mxa)
2288670SJose.Borrego@Sun.COM {
2298670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKLM"));
2308670SJose.Borrego@Sun.COM }
2318670SJose.Borrego@Sun.COM 
2328670SJose.Borrego@Sun.COM static int
2338670SJose.Borrego@Sun.COM winreg_s_OpenHKPD(void *arg, ndr_xa_t *mxa)
2348474SJose.Borrego@Sun.COM {
2358670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKPD"));
2368670SJose.Borrego@Sun.COM }
2378670SJose.Borrego@Sun.COM 
2388670SJose.Borrego@Sun.COM static int
2398670SJose.Borrego@Sun.COM winreg_s_OpenHKU(void *arg, ndr_xa_t *mxa)
2408670SJose.Borrego@Sun.COM {
2418670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKU"));
2428670SJose.Borrego@Sun.COM }
2438670SJose.Borrego@Sun.COM 
2448670SJose.Borrego@Sun.COM static int
2458670SJose.Borrego@Sun.COM winreg_s_OpenHKCC(void *arg, ndr_xa_t *mxa)
2468670SJose.Borrego@Sun.COM {
2478670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKCC"));
2488670SJose.Borrego@Sun.COM }
2498474SJose.Borrego@Sun.COM 
2508670SJose.Borrego@Sun.COM static int
2518670SJose.Borrego@Sun.COM winreg_s_OpenHKDD(void *arg, ndr_xa_t *mxa)
2528670SJose.Borrego@Sun.COM {
2538670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKDD"));
2548670SJose.Borrego@Sun.COM }
2558474SJose.Borrego@Sun.COM 
2568670SJose.Borrego@Sun.COM static int
2578670SJose.Borrego@Sun.COM winreg_s_OpenHKPT(void *arg, ndr_xa_t *mxa)
2588670SJose.Borrego@Sun.COM {
2598670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKPT"));
2608670SJose.Borrego@Sun.COM }
2618670SJose.Borrego@Sun.COM 
2628670SJose.Borrego@Sun.COM static int
2638670SJose.Borrego@Sun.COM winreg_s_OpenHKPN(void *arg, ndr_xa_t *mxa)
2648670SJose.Borrego@Sun.COM {
2658670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKPN"));
2668474SJose.Borrego@Sun.COM }
2678474SJose.Borrego@Sun.COM 
2688474SJose.Borrego@Sun.COM /*
2698670SJose.Borrego@Sun.COM  * winreg_s_OpenHK
2708474SJose.Borrego@Sun.COM  *
2718670SJose.Borrego@Sun.COM  * Common code to open root HKEYs.
2728474SJose.Borrego@Sun.COM  */
2738474SJose.Borrego@Sun.COM static int
2748670SJose.Borrego@Sun.COM winreg_s_OpenHK(void *arg, ndr_xa_t *mxa, const char *hkey)
2758474SJose.Borrego@Sun.COM {
2768670SJose.Borrego@Sun.COM 	struct winreg_OpenHKCR *param = arg;
2778474SJose.Borrego@Sun.COM 	ndr_hdid_t *id;
2788670SJose.Borrego@Sun.COM 	char *dupkey;
2798474SJose.Borrego@Sun.COM 
2808670SJose.Borrego@Sun.COM 	if ((dupkey = strdup(hkey)) == NULL) {
2818474SJose.Borrego@Sun.COM 		bzero(&param->handle, sizeof (winreg_handle_t));
2828670SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
2838670SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
2848474SJose.Borrego@Sun.COM 	}
2858474SJose.Borrego@Sun.COM 
2868670SJose.Borrego@Sun.COM 	if ((id = ndr_hdalloc(mxa, dupkey)) == NULL) {
2878670SJose.Borrego@Sun.COM 		free(dupkey);
2888474SJose.Borrego@Sun.COM 		bzero(&param->handle, sizeof (winreg_handle_t));
2898474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
2908474SJose.Borrego@Sun.COM 	} else {
2918474SJose.Borrego@Sun.COM 		bcopy(id, &param->handle, sizeof (winreg_handle_t));
2928474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
2938474SJose.Borrego@Sun.COM 	}
2948474SJose.Borrego@Sun.COM 
2958474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
2968474SJose.Borrego@Sun.COM }
2978474SJose.Borrego@Sun.COM 
2988474SJose.Borrego@Sun.COM /*
2998474SJose.Borrego@Sun.COM  * winreg_s_Close
3008474SJose.Borrego@Sun.COM  *
3018474SJose.Borrego@Sun.COM  * This is a request to close the WINREG interface specified by the
3028474SJose.Borrego@Sun.COM  * handle. We don't track handles (yet), so just zero out the handle
3038474SJose.Borrego@Sun.COM  * and return NDR_DRC_OK. Setting the handle to zero appears to be
3048474SJose.Borrego@Sun.COM  * standard behaviour.
3058474SJose.Borrego@Sun.COM  */
3068474SJose.Borrego@Sun.COM static int
3078474SJose.Borrego@Sun.COM winreg_s_Close(void *arg, ndr_xa_t *mxa)
3088474SJose.Borrego@Sun.COM {
3098474SJose.Borrego@Sun.COM 	struct winreg_Close *param = arg;
3108474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
3118670SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
3128670SJose.Borrego@Sun.COM 
3138670SJose.Borrego@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
3148670SJose.Borrego@Sun.COM 		free(hd->nh_data);
3158670SJose.Borrego@Sun.COM 		hd->nh_data = NULL;
3168670SJose.Borrego@Sun.COM 	}
3178474SJose.Borrego@Sun.COM 
3188474SJose.Borrego@Sun.COM 	ndr_hdfree(mxa, id);
3198474SJose.Borrego@Sun.COM 
3208474SJose.Borrego@Sun.COM 	bzero(&param->result_handle, sizeof (winreg_handle_t));
3218474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
3228474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
3238474SJose.Borrego@Sun.COM }
3248474SJose.Borrego@Sun.COM 
3258474SJose.Borrego@Sun.COM /*
3268474SJose.Borrego@Sun.COM  * winreg_s_CreateKey
3278474SJose.Borrego@Sun.COM  */
3288474SJose.Borrego@Sun.COM static int
3298474SJose.Borrego@Sun.COM winreg_s_CreateKey(void *arg, ndr_xa_t *mxa)
3308474SJose.Borrego@Sun.COM {
3318474SJose.Borrego@Sun.COM 	struct winreg_CreateKey *param = arg;
3328474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
3338474SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
3348474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
3358474SJose.Borrego@Sun.COM 	char *subkey;
3368670SJose.Borrego@Sun.COM 	char *dupkey;
3378474SJose.Borrego@Sun.COM 	DWORD *action;
3388474SJose.Borrego@Sun.COM 
3398474SJose.Borrego@Sun.COM 	subkey = (char *)param->subkey.str;
3408474SJose.Borrego@Sun.COM 
3418474SJose.Borrego@Sun.COM 	if (!ndr_is_admin(mxa) || (subkey == NULL)) {
3428474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
3438474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
3448474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
3458474SJose.Borrego@Sun.COM 	}
3468474SJose.Borrego@Sun.COM 
3478474SJose.Borrego@Sun.COM 	hd = ndr_hdlookup(mxa, id);
3488474SJose.Borrego@Sun.COM 	if (hd == NULL) {
3498474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
3508474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
3518474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
3528474SJose.Borrego@Sun.COM 	}
3538474SJose.Borrego@Sun.COM 
3548474SJose.Borrego@Sun.COM 	if ((action = NDR_NEW(mxa, DWORD)) == NULL) {
3558474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
3568474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
3578474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
3588474SJose.Borrego@Sun.COM 	}
3598474SJose.Borrego@Sun.COM 
3608474SJose.Borrego@Sun.COM 	if (list_is_empty(&winreg_keylist.kl_list))
3618474SJose.Borrego@Sun.COM 		goto new_key;
3628474SJose.Borrego@Sun.COM 
3638474SJose.Borrego@Sun.COM 	/*
3648474SJose.Borrego@Sun.COM 	 * Check for an existing key.
3658474SJose.Borrego@Sun.COM 	 */
3668474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
3678474SJose.Borrego@Sun.COM 	do {
3688474SJose.Borrego@Sun.COM 		if (strcasecmp(subkey, key->sk_name) == 0) {
3698474SJose.Borrego@Sun.COM 			bcopy(&key->sk_handle, &param->result_handle,
3708474SJose.Borrego@Sun.COM 			    sizeof (winreg_handle_t));
3718474SJose.Borrego@Sun.COM 			*action = WINREG_ACTION_EXISTING_KEY;
3728474SJose.Borrego@Sun.COM 			param->action = action;
3738474SJose.Borrego@Sun.COM 			param->status = ERROR_SUCCESS;
3748474SJose.Borrego@Sun.COM 			return (NDR_DRC_OK);
3758474SJose.Borrego@Sun.COM 		}
3768474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
3778474SJose.Borrego@Sun.COM 
3788474SJose.Borrego@Sun.COM new_key:
3798474SJose.Borrego@Sun.COM 	/*
3808474SJose.Borrego@Sun.COM 	 * Create a new key.
3818474SJose.Borrego@Sun.COM 	 */
3828670SJose.Borrego@Sun.COM 	if ((dupkey = strdup(subkey)) == NULL) {
3838670SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
3848670SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
3858670SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
3868670SJose.Borrego@Sun.COM 	}
3878670SJose.Borrego@Sun.COM 
3888670SJose.Borrego@Sun.COM 	id = ndr_hdalloc(mxa, dupkey);
3898474SJose.Borrego@Sun.COM 	key = malloc(sizeof (winreg_subkey_t));
3908474SJose.Borrego@Sun.COM 
3918474SJose.Borrego@Sun.COM 	if ((id == NULL) || (key == NULL)) {
3928670SJose.Borrego@Sun.COM 		free(dupkey);
3938474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
3948474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
3958474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
3968474SJose.Borrego@Sun.COM 	}
3978474SJose.Borrego@Sun.COM 
3988474SJose.Borrego@Sun.COM 	bcopy(id, &key->sk_handle, sizeof (ndr_hdid_t));
3998474SJose.Borrego@Sun.COM 	(void) strlcpy(key->sk_name, subkey, MAXPATHLEN);
4008474SJose.Borrego@Sun.COM 	key->sk_predefined = B_FALSE;
4018474SJose.Borrego@Sun.COM 	list_insert_tail(&winreg_keylist.kl_list, key);
4028474SJose.Borrego@Sun.COM 	++winreg_keylist.kl_count;
4038474SJose.Borrego@Sun.COM 
4048474SJose.Borrego@Sun.COM 	bcopy(id, &param->result_handle, sizeof (winreg_handle_t));
4058474SJose.Borrego@Sun.COM 	*action = WINREG_ACTION_NEW_KEY;
4068474SJose.Borrego@Sun.COM 	param->action = action;
4078474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
4088474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
4098474SJose.Borrego@Sun.COM }
4108474SJose.Borrego@Sun.COM 
4118474SJose.Borrego@Sun.COM /*
4128474SJose.Borrego@Sun.COM  * winreg_s_DeleteKey
4138474SJose.Borrego@Sun.COM  */
4148474SJose.Borrego@Sun.COM static int
4158474SJose.Borrego@Sun.COM winreg_s_DeleteKey(void *arg, ndr_xa_t *mxa)
4168474SJose.Borrego@Sun.COM {
4178474SJose.Borrego@Sun.COM 	struct winreg_DeleteKey *param = arg;
4188474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
4198670SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
4208474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
4218474SJose.Borrego@Sun.COM 	char *subkey;
4228474SJose.Borrego@Sun.COM 
4238474SJose.Borrego@Sun.COM 	subkey = (char *)param->subkey.str;
4248474SJose.Borrego@Sun.COM 
4258474SJose.Borrego@Sun.COM 	if (!ndr_is_admin(mxa) || (subkey == NULL)) {
4268474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
4278474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
4288474SJose.Borrego@Sun.COM 	}
4298474SJose.Borrego@Sun.COM 
4308474SJose.Borrego@Sun.COM 	if ((ndr_hdlookup(mxa, id) == NULL) ||
4318474SJose.Borrego@Sun.COM 	    list_is_empty(&winreg_keylist.kl_list) ||
4328474SJose.Borrego@Sun.COM 	    winreg_key_has_subkey(subkey)) {
4338474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
4348474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
4358474SJose.Borrego@Sun.COM 	}
4368474SJose.Borrego@Sun.COM 
4378474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
4388474SJose.Borrego@Sun.COM 	do {
4398474SJose.Borrego@Sun.COM 		if (strcasecmp(subkey, key->sk_name) == 0) {
4408474SJose.Borrego@Sun.COM 			if (key->sk_predefined == B_TRUE) {
4418474SJose.Borrego@Sun.COM 				/* Predefined keys cannot be deleted */
4428474SJose.Borrego@Sun.COM 				break;
4438474SJose.Borrego@Sun.COM 			}
4448474SJose.Borrego@Sun.COM 
4458474SJose.Borrego@Sun.COM 			list_remove(&winreg_keylist.kl_list, key);
4468474SJose.Borrego@Sun.COM 			--winreg_keylist.kl_count;
4478670SJose.Borrego@Sun.COM 
4488670SJose.Borrego@Sun.COM 			hd = ndr_hdlookup(mxa, &key->sk_handle);
4498670SJose.Borrego@Sun.COM 			if (hd != NULL) {
4508670SJose.Borrego@Sun.COM 				free(hd->nh_data);
4518670SJose.Borrego@Sun.COM 				hd->nh_data = NULL;
4528670SJose.Borrego@Sun.COM 			}
4538670SJose.Borrego@Sun.COM 
4548474SJose.Borrego@Sun.COM 			ndr_hdfree(mxa, &key->sk_handle);
4558474SJose.Borrego@Sun.COM 			free(key);
4568474SJose.Borrego@Sun.COM 			param->status = ERROR_SUCCESS;
4578474SJose.Borrego@Sun.COM 			return (NDR_DRC_OK);
4588474SJose.Borrego@Sun.COM 		}
4598474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
4608474SJose.Borrego@Sun.COM 
4618474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
4628474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
4638474SJose.Borrego@Sun.COM }
4648474SJose.Borrego@Sun.COM 
4658474SJose.Borrego@Sun.COM static boolean_t
4668474SJose.Borrego@Sun.COM winreg_key_has_subkey(const char *subkey)
4678474SJose.Borrego@Sun.COM {
4688474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
4698474SJose.Borrego@Sun.COM 	int keylen;
4708474SJose.Borrego@Sun.COM 
4718474SJose.Borrego@Sun.COM 	if (list_is_empty(&winreg_keylist.kl_list))
4728474SJose.Borrego@Sun.COM 		return (B_FALSE);
4738474SJose.Borrego@Sun.COM 
4748474SJose.Borrego@Sun.COM 	keylen = strlen(subkey);
4758474SJose.Borrego@Sun.COM 
4768474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
4778474SJose.Borrego@Sun.COM 	do {
4788474SJose.Borrego@Sun.COM 		if (strncasecmp(subkey, key->sk_name, keylen) == 0) {
4798474SJose.Borrego@Sun.COM 			/*
4808474SJose.Borrego@Sun.COM 			 * Potential match.  If sk_name is longer than
4818474SJose.Borrego@Sun.COM 			 * subkey, then sk_name is a subkey of our key.
4828474SJose.Borrego@Sun.COM 			 */
4838474SJose.Borrego@Sun.COM 			if (keylen < strlen(key->sk_name))
4848474SJose.Borrego@Sun.COM 				return (B_TRUE);
4858474SJose.Borrego@Sun.COM 		}
4868474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
4878474SJose.Borrego@Sun.COM 
4888474SJose.Borrego@Sun.COM 	return (B_FALSE);
4898474SJose.Borrego@Sun.COM }
4908474SJose.Borrego@Sun.COM 
4918474SJose.Borrego@Sun.COM static char *
4928670SJose.Borrego@Sun.COM winreg_enum_subkey(ndr_xa_t *mxa, const char *subkey, uint32_t index)
4938474SJose.Borrego@Sun.COM {
4948474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
4958670SJose.Borrego@Sun.COM 	char *entry;
4968670SJose.Borrego@Sun.COM 	char *p;
4978670SJose.Borrego@Sun.COM 	int subkeylen;
4988670SJose.Borrego@Sun.COM 	int count = 0;
4998474SJose.Borrego@Sun.COM 
5008474SJose.Borrego@Sun.COM 	if (subkey == NULL)
5018474SJose.Borrego@Sun.COM 		return (NULL);
5028474SJose.Borrego@Sun.COM 
5038474SJose.Borrego@Sun.COM 	if (list_is_empty(&winreg_keylist.kl_list))
5048474SJose.Borrego@Sun.COM 		return (NULL);
5058474SJose.Borrego@Sun.COM 
5068670SJose.Borrego@Sun.COM 	subkeylen = strlen(subkey);
5078670SJose.Borrego@Sun.COM 
5088670SJose.Borrego@Sun.COM 	for (key = list_head(&winreg_keylist.kl_list);
5098670SJose.Borrego@Sun.COM 	    key != NULL; key = list_next(&winreg_keylist.kl_list, key)) {
5108670SJose.Borrego@Sun.COM 		if (strncasecmp(subkey, key->sk_name, subkeylen) == 0) {
5118670SJose.Borrego@Sun.COM 			p = key->sk_name + subkeylen;
5128670SJose.Borrego@Sun.COM 
5138670SJose.Borrego@Sun.COM 			if ((*p != '\\') || (*p == '\0')) {
5148670SJose.Borrego@Sun.COM 				/*
5158670SJose.Borrego@Sun.COM 				 * Not the same subkey or an exact match.
5168670SJose.Borrego@Sun.COM 				 * We're looking for children of subkey.
5178670SJose.Borrego@Sun.COM 				 */
5188670SJose.Borrego@Sun.COM 				continue;
5198670SJose.Borrego@Sun.COM 			}
5208670SJose.Borrego@Sun.COM 
5218670SJose.Borrego@Sun.COM 			++p;
5228670SJose.Borrego@Sun.COM 
5238670SJose.Borrego@Sun.COM 			if (count < index) {
5248670SJose.Borrego@Sun.COM 				++count;
5258670SJose.Borrego@Sun.COM 				continue;
5268670SJose.Borrego@Sun.COM 			}
5278670SJose.Borrego@Sun.COM 
5288670SJose.Borrego@Sun.COM 			if ((entry = NDR_STRDUP(mxa, p)) == NULL)
5298670SJose.Borrego@Sun.COM 				return (NULL);
5308670SJose.Borrego@Sun.COM 
5318670SJose.Borrego@Sun.COM 			if ((p = strchr(entry, '\\')) != NULL)
5328670SJose.Borrego@Sun.COM 				*p = '\0';
5338670SJose.Borrego@Sun.COM 
5348670SJose.Borrego@Sun.COM 			return (entry);
5358474SJose.Borrego@Sun.COM 		}
5368670SJose.Borrego@Sun.COM 	}
5378474SJose.Borrego@Sun.COM 
5388474SJose.Borrego@Sun.COM 	return (NULL);
5398474SJose.Borrego@Sun.COM }
5408474SJose.Borrego@Sun.COM 
5418474SJose.Borrego@Sun.COM /*
5428474SJose.Borrego@Sun.COM  * winreg_s_DeleteValue
5438474SJose.Borrego@Sun.COM  */
5448474SJose.Borrego@Sun.COM /*ARGSUSED*/
5458474SJose.Borrego@Sun.COM static int
5468474SJose.Borrego@Sun.COM winreg_s_DeleteValue(void *arg, ndr_xa_t *mxa)
5478474SJose.Borrego@Sun.COM {
5488474SJose.Borrego@Sun.COM 	struct winreg_DeleteValue *param = arg;
5498474SJose.Borrego@Sun.COM 
5508474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
5518474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
5528474SJose.Borrego@Sun.COM }
5538474SJose.Borrego@Sun.COM 
5548474SJose.Borrego@Sun.COM /*
5558474SJose.Borrego@Sun.COM  * winreg_s_EnumKey
5568474SJose.Borrego@Sun.COM  */
5578474SJose.Borrego@Sun.COM static int
5588474SJose.Borrego@Sun.COM winreg_s_EnumKey(void *arg, ndr_xa_t *mxa)
5598474SJose.Borrego@Sun.COM {
5608474SJose.Borrego@Sun.COM 	struct winreg_EnumKey *param = arg;
5618474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
5628670SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
5638670SJose.Borrego@Sun.COM 	char *subkey;
5648670SJose.Borrego@Sun.COM 	char *name = NULL;
5658474SJose.Borrego@Sun.COM 
5668670SJose.Borrego@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) != NULL)
5678670SJose.Borrego@Sun.COM 		name = hd->nh_data;
5688474SJose.Borrego@Sun.COM 
5698670SJose.Borrego@Sun.COM 	if (hd == NULL || name == NULL) {
5708474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumKey));
5718474SJose.Borrego@Sun.COM 		param->status = ERROR_NO_MORE_ITEMS;
5728474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5738474SJose.Borrego@Sun.COM 	}
5748474SJose.Borrego@Sun.COM 
5758670SJose.Borrego@Sun.COM 	subkey = winreg_enum_subkey(mxa, name, param->index);
5768670SJose.Borrego@Sun.COM 	if (subkey == NULL) {
5778474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumKey));
5788670SJose.Borrego@Sun.COM 		param->status = ERROR_NO_MORE_ITEMS;
5798474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5808474SJose.Borrego@Sun.COM 	}
5818474SJose.Borrego@Sun.COM 
5828670SJose.Borrego@Sun.COM 	if (NDR_MSTRING(mxa, subkey, (ndr_mstring_t *)&param->name_out) == -1) {
5838474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumKey));
5848474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
5858474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5868474SJose.Borrego@Sun.COM 	}
5878670SJose.Borrego@Sun.COM 	/*
5888670SJose.Borrego@Sun.COM 	 * This request requires that the length includes the null.
5898670SJose.Borrego@Sun.COM 	 */
5908670SJose.Borrego@Sun.COM 	param->name_out.length = param->name_out.allosize;
5918474SJose.Borrego@Sun.COM 
5928474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
5938474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
5948474SJose.Borrego@Sun.COM }
5958474SJose.Borrego@Sun.COM 
5968474SJose.Borrego@Sun.COM /*
5978474SJose.Borrego@Sun.COM  * winreg_s_EnumValue
5988474SJose.Borrego@Sun.COM  */
5998474SJose.Borrego@Sun.COM static int
6008474SJose.Borrego@Sun.COM winreg_s_EnumValue(void *arg, ndr_xa_t *mxa)
6018474SJose.Borrego@Sun.COM {
6028474SJose.Borrego@Sun.COM 	struct winreg_EnumValue *param = arg;
6038474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
6048474SJose.Borrego@Sun.COM 
6058474SJose.Borrego@Sun.COM 	if (ndr_hdlookup(mxa, id) == NULL) {
6068474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumValue));
6078474SJose.Borrego@Sun.COM 		param->status = ERROR_NO_MORE_ITEMS;
6088474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6098474SJose.Borrego@Sun.COM 	}
6108474SJose.Borrego@Sun.COM 
6118474SJose.Borrego@Sun.COM 	bzero(param, sizeof (struct winreg_EnumValue));
6128474SJose.Borrego@Sun.COM 	param->status = ERROR_NO_MORE_ITEMS;
6138474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6148474SJose.Borrego@Sun.COM }
6158474SJose.Borrego@Sun.COM 
6168474SJose.Borrego@Sun.COM /*
6178474SJose.Borrego@Sun.COM  * winreg_s_FlushKey
6188474SJose.Borrego@Sun.COM  *
6198474SJose.Borrego@Sun.COM  * Flush the attributes associated with the specified open key to disk.
6208474SJose.Borrego@Sun.COM  */
6218474SJose.Borrego@Sun.COM static int
6228474SJose.Borrego@Sun.COM winreg_s_FlushKey(void *arg, ndr_xa_t *mxa)
6238474SJose.Borrego@Sun.COM {
6248474SJose.Borrego@Sun.COM 	struct winreg_FlushKey *param = arg;
6258474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
6268474SJose.Borrego@Sun.COM 
6278474SJose.Borrego@Sun.COM 	if (ndr_hdlookup(mxa, id) == NULL)
6288474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
6298474SJose.Borrego@Sun.COM 	else
6308474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
6318474SJose.Borrego@Sun.COM 
6328474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6338474SJose.Borrego@Sun.COM }
6348474SJose.Borrego@Sun.COM 
6358474SJose.Borrego@Sun.COM /*
6368474SJose.Borrego@Sun.COM  * winreg_s_GetKeySec
6378474SJose.Borrego@Sun.COM  */
6388474SJose.Borrego@Sun.COM static int
6398474SJose.Borrego@Sun.COM winreg_s_GetKeySec(void *arg, ndr_xa_t *mxa)
6408474SJose.Borrego@Sun.COM {
6418474SJose.Borrego@Sun.COM 	struct winreg_GetKeySec *param = arg;
642*11447Samw@Sun.COM 	struct winreg_value	*sd_buf;
643*11447Samw@Sun.COM 	smb_sd_t		sd;
644*11447Samw@Sun.COM 	uint32_t		sd_len;
645*11447Samw@Sun.COM 	uint32_t		status;
6468474SJose.Borrego@Sun.COM 
647*11447Samw@Sun.COM 	bzero(&sd, sizeof (smb_sd_t));
648*11447Samw@Sun.COM 
649*11447Samw@Sun.COM 	if ((status = winreg_sd_format(&sd)) != ERROR_SUCCESS)
650*11447Samw@Sun.COM 		goto winreg_getkeysec_error;
651*11447Samw@Sun.COM 
652*11447Samw@Sun.COM 	sd_len = smb_sd_len(&sd, SMB_ALL_SECINFO);
653*11447Samw@Sun.COM 
654*11447Samw@Sun.COM 	param->sd = NDR_MALLOC(mxa, sizeof (struct winreg_secdesc));
655*11447Samw@Sun.COM 	if (param->sd == NULL) {
656*11447Samw@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
657*11447Samw@Sun.COM 		goto winreg_getkeysec_error;
658*11447Samw@Sun.COM 	}
659*11447Samw@Sun.COM 
660*11447Samw@Sun.COM 	param->sd->sd_len = sd_len;
661*11447Samw@Sun.COM 	param->sd->sd_size = sd_len;
662*11447Samw@Sun.COM 
663*11447Samw@Sun.COM 	sd_buf = NDR_MALLOC(mxa, sd_len + sizeof (struct winreg_value));
664*11447Samw@Sun.COM 	param->sd->sd_buf = sd_buf;
665*11447Samw@Sun.COM 
666*11447Samw@Sun.COM 	sd_buf->vc_first_is = 0;
667*11447Samw@Sun.COM 	sd_buf->vc_length_is = sd_len;
668*11447Samw@Sun.COM 	param->status = srvsvc_sd_set_relative(&sd, sd_buf->value);
669*11447Samw@Sun.COM 
670*11447Samw@Sun.COM 	smb_sd_term(&sd);
671*11447Samw@Sun.COM 	return (NDR_DRC_OK);
672*11447Samw@Sun.COM 
673*11447Samw@Sun.COM winreg_getkeysec_error:
674*11447Samw@Sun.COM 	smb_sd_term(&sd);
6758474SJose.Borrego@Sun.COM 	bzero(param, sizeof (struct winreg_GetKeySec));
676*11447Samw@Sun.COM 	param->status = status;
6778474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6788474SJose.Borrego@Sun.COM }
6798474SJose.Borrego@Sun.COM 
680*11447Samw@Sun.COM static uint32_t
681*11447Samw@Sun.COM winreg_sd_format(smb_sd_t *sd)
682*11447Samw@Sun.COM {
683*11447Samw@Sun.COM 	smb_fssd_t	fs_sd;
684*11447Samw@Sun.COM 	acl_t		*acl;
685*11447Samw@Sun.COM 	uint32_t	status = ERROR_SUCCESS;
686*11447Samw@Sun.COM 
687*11447Samw@Sun.COM 	if (acl_fromtext("owner@:rwxpdDaARWcCos::allow", &acl) != 0)
688*11447Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
689*11447Samw@Sun.COM 
690*11447Samw@Sun.COM 	smb_fssd_init(&fs_sd, SMB_ALL_SECINFO, SMB_FSSD_FLAGS_DIR);
691*11447Samw@Sun.COM 	fs_sd.sd_uid = 0;
692*11447Samw@Sun.COM 	fs_sd.sd_gid = 0;
693*11447Samw@Sun.COM 	fs_sd.sd_zdacl = acl;
694*11447Samw@Sun.COM 	fs_sd.sd_zsacl = NULL;
695*11447Samw@Sun.COM 
696*11447Samw@Sun.COM 	if (smb_sd_fromfs(&fs_sd, sd) != NT_STATUS_SUCCESS)
697*11447Samw@Sun.COM 		status = ERROR_ACCESS_DENIED;
698*11447Samw@Sun.COM 	smb_fssd_term(&fs_sd);
699*11447Samw@Sun.COM 	return (status);
700*11447Samw@Sun.COM }
701*11447Samw@Sun.COM 
7028474SJose.Borrego@Sun.COM /*
7038474SJose.Borrego@Sun.COM  * winreg_s_NotifyChange
7048474SJose.Borrego@Sun.COM  */
7058474SJose.Borrego@Sun.COM static int
7068474SJose.Borrego@Sun.COM winreg_s_NotifyChange(void *arg, ndr_xa_t *mxa)
7078474SJose.Borrego@Sun.COM {
7088474SJose.Borrego@Sun.COM 	struct winreg_NotifyChange *param = arg;
7098474SJose.Borrego@Sun.COM 
7108474SJose.Borrego@Sun.COM 	if (ndr_is_admin(mxa))
7118474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
7128474SJose.Borrego@Sun.COM 	else
7138474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
7148474SJose.Borrego@Sun.COM 
7158474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
7168474SJose.Borrego@Sun.COM }
7178474SJose.Borrego@Sun.COM 
7188474SJose.Borrego@Sun.COM /*
7198474SJose.Borrego@Sun.COM  * winreg_s_OpenKey
7208474SJose.Borrego@Sun.COM  *
7218474SJose.Borrego@Sun.COM  * This is a request to open a windows registry key.
7228474SJose.Borrego@Sun.COM  * If we recognize the key, we return a handle.
7238474SJose.Borrego@Sun.COM  *
7248474SJose.Borrego@Sun.COM  * Returns:
7258474SJose.Borrego@Sun.COM  *	ERROR_SUCCESS		Valid handle returned.
7268474SJose.Borrego@Sun.COM  *	ERROR_FILE_NOT_FOUND	No key or unable to allocate a handle.
7278474SJose.Borrego@Sun.COM  */
7288474SJose.Borrego@Sun.COM static int
7298474SJose.Borrego@Sun.COM winreg_s_OpenKey(void *arg, ndr_xa_t *mxa)
7308474SJose.Borrego@Sun.COM {
7318474SJose.Borrego@Sun.COM 	struct winreg_OpenKey *param = arg;
7329914Samw@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
7339914Samw@Sun.COM 	ndr_handle_t *hd;
7348474SJose.Borrego@Sun.COM 	char *subkey = (char *)param->name.str;
7358474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
7368670SJose.Borrego@Sun.COM 	char *dupkey;
7378474SJose.Borrego@Sun.COM 
7389914Samw@Sun.COM 	if (subkey == NULL || *subkey == '\0') {
7399914Samw@Sun.COM 		if ((hd = ndr_hdlookup(mxa, id)) != NULL)
7409914Samw@Sun.COM 			subkey = hd->nh_data;
7419914Samw@Sun.COM 	}
7429914Samw@Sun.COM 
7439914Samw@Sun.COM 	id = NULL;
7449914Samw@Sun.COM 
7458670SJose.Borrego@Sun.COM 	if (subkey == NULL || list_is_empty(&winreg_keylist.kl_list)) {
7468474SJose.Borrego@Sun.COM 		bzero(&param->result_handle, sizeof (winreg_handle_t));
7478474SJose.Borrego@Sun.COM 		param->status = ERROR_FILE_NOT_FOUND;
7488474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
7498474SJose.Borrego@Sun.COM 	}
7508474SJose.Borrego@Sun.COM 
7518474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
7528474SJose.Borrego@Sun.COM 	do {
7538474SJose.Borrego@Sun.COM 		if (strcasecmp(subkey, key->sk_name) == 0) {
7548670SJose.Borrego@Sun.COM 			if (key->sk_predefined == B_TRUE) {
7558670SJose.Borrego@Sun.COM 				if ((dupkey = strdup(subkey)) == NULL)
7568670SJose.Borrego@Sun.COM 					break;
7578670SJose.Borrego@Sun.COM 
7588670SJose.Borrego@Sun.COM 				id = ndr_hdalloc(mxa, dupkey);
7598670SJose.Borrego@Sun.COM 				if (id == NULL)
7608670SJose.Borrego@Sun.COM 					free(dupkey);
7618670SJose.Borrego@Sun.COM 			} else {
7628474SJose.Borrego@Sun.COM 				id = &key->sk_handle;
7638670SJose.Borrego@Sun.COM 			}
7648474SJose.Borrego@Sun.COM 
7658474SJose.Borrego@Sun.COM 			if (id == NULL)
7668474SJose.Borrego@Sun.COM 				break;
7678474SJose.Borrego@Sun.COM 
7688474SJose.Borrego@Sun.COM 			bcopy(id, &param->result_handle,
7698474SJose.Borrego@Sun.COM 			    sizeof (winreg_handle_t));
7708474SJose.Borrego@Sun.COM 			param->status = ERROR_SUCCESS;
7718474SJose.Borrego@Sun.COM 			return (NDR_DRC_OK);
7728474SJose.Borrego@Sun.COM 		}
7738474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
7748474SJose.Borrego@Sun.COM 
7758474SJose.Borrego@Sun.COM 	bzero(&param->result_handle, sizeof (winreg_handle_t));
7768474SJose.Borrego@Sun.COM 	param->status = ERROR_FILE_NOT_FOUND;
7778474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
7788474SJose.Borrego@Sun.COM }
7798474SJose.Borrego@Sun.COM 
7808474SJose.Borrego@Sun.COM /*
7818474SJose.Borrego@Sun.COM  * winreg_s_QueryKey
7828474SJose.Borrego@Sun.COM  */
7838474SJose.Borrego@Sun.COM /*ARGSUSED*/
7848474SJose.Borrego@Sun.COM static int
7858474SJose.Borrego@Sun.COM winreg_s_QueryKey(void *arg, ndr_xa_t *mxa)
7868474SJose.Borrego@Sun.COM {
7878474SJose.Borrego@Sun.COM 	struct winreg_QueryKey *param = arg;
7888474SJose.Borrego@Sun.COM 	int rc;
7898474SJose.Borrego@Sun.COM 	winreg_string_t	*name;
7908474SJose.Borrego@Sun.COM 
7918474SJose.Borrego@Sun.COM 	name = (winreg_string_t	*)&param->name;
7928474SJose.Borrego@Sun.COM 	bzero(param, sizeof (struct winreg_QueryKey));
7938474SJose.Borrego@Sun.COM 	if ((name = NDR_NEW(mxa, winreg_string_t)) != NULL)
7948474SJose.Borrego@Sun.COM 		rc = NDR_MSTRING(mxa, "", (ndr_mstring_t *)name);
7958474SJose.Borrego@Sun.COM 
7968474SJose.Borrego@Sun.COM 	if ((name == NULL) || (rc != 0)) {
7978474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_QueryKey));
7988474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
7998474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8008474SJose.Borrego@Sun.COM 	}
8018474SJose.Borrego@Sun.COM 
8028474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
8038474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
8048474SJose.Borrego@Sun.COM }
8058474SJose.Borrego@Sun.COM 
8068474SJose.Borrego@Sun.COM /*
8078474SJose.Borrego@Sun.COM  * winreg_s_QueryValue
8088474SJose.Borrego@Sun.COM  *
8098474SJose.Borrego@Sun.COM  * This is a request to get the value associated with a specified name.
8108474SJose.Borrego@Sun.COM  *
8118474SJose.Borrego@Sun.COM  * Returns:
8128474SJose.Borrego@Sun.COM  *	ERROR_SUCCESS		Value returned.
8138474SJose.Borrego@Sun.COM  *	ERROR_FILE_NOT_FOUND	PrimaryModule is not supported.
8148474SJose.Borrego@Sun.COM  *	ERROR_CANTREAD          No such name or memory problem.
8158474SJose.Borrego@Sun.COM  */
8168474SJose.Borrego@Sun.COM static int
8178474SJose.Borrego@Sun.COM winreg_s_QueryValue(void *arg, ndr_xa_t *mxa)
8188474SJose.Borrego@Sun.COM {
8198474SJose.Borrego@Sun.COM 	struct winreg_QueryValue *param = arg;
8208474SJose.Borrego@Sun.COM 	struct winreg_value *pv;
8218474SJose.Borrego@Sun.COM 	char *name;
8228474SJose.Borrego@Sun.COM 	char *value;
8238474SJose.Borrego@Sun.COM 	DWORD slen;
8248474SJose.Borrego@Sun.COM 	DWORD msize;
8258474SJose.Borrego@Sun.COM 
8268474SJose.Borrego@Sun.COM 	name = (char *)param->value_name.str;
8278474SJose.Borrego@Sun.COM 
8288474SJose.Borrego@Sun.COM 	if (strcasecmp(name, "PrimaryModule") == 0) {
8298474SJose.Borrego@Sun.COM 		param->status = ERROR_FILE_NOT_FOUND;
8308474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8318474SJose.Borrego@Sun.COM 	}
8328474SJose.Borrego@Sun.COM 
8338474SJose.Borrego@Sun.COM 	if ((value = winreg_lookup_value(name)) == NULL) {
8348474SJose.Borrego@Sun.COM 		param->status = ERROR_CANTREAD;
8358474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8368474SJose.Borrego@Sun.COM 	}
8378474SJose.Borrego@Sun.COM 
83810966SJordan.Brown@Sun.COM 	slen = smb_wcequiv_strlen(value) + sizeof (smb_wchar_t);
8398474SJose.Borrego@Sun.COM 	msize = sizeof (struct winreg_value) + slen;
8408474SJose.Borrego@Sun.COM 
8418474SJose.Borrego@Sun.COM 	param->value = (struct winreg_value *)NDR_MALLOC(mxa, msize);
8428474SJose.Borrego@Sun.COM 	param->type = NDR_NEW(mxa, DWORD);
8438474SJose.Borrego@Sun.COM 	param->value_size = NDR_NEW(mxa, DWORD);
8448474SJose.Borrego@Sun.COM 	param->value_size_total = NDR_NEW(mxa, DWORD);
8458474SJose.Borrego@Sun.COM 
8468474SJose.Borrego@Sun.COM 	if (param->value == NULL || param->type == NULL ||
8478474SJose.Borrego@Sun.COM 	    param->value_size == NULL || param->value_size_total == NULL) {
8488474SJose.Borrego@Sun.COM 		param->status = ERROR_CANTREAD;
8498474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8508474SJose.Borrego@Sun.COM 	}
8518474SJose.Borrego@Sun.COM 
8528474SJose.Borrego@Sun.COM 	bzero(param->value, msize);
8538474SJose.Borrego@Sun.COM 	pv = param->value;
8548474SJose.Borrego@Sun.COM 	pv->vc_first_is = 0;
8558474SJose.Borrego@Sun.COM 	pv->vc_length_is = slen;
8568474SJose.Borrego@Sun.COM 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
85710966SJordan.Brown@Sun.COM 	(void) ndr_mbstowcs(NULL, (smb_wchar_t *)pv->value, value, slen);
8588474SJose.Borrego@Sun.COM 
8598474SJose.Borrego@Sun.COM 	*param->type = 1;
8608474SJose.Borrego@Sun.COM 	*param->value_size = slen;
8618474SJose.Borrego@Sun.COM 	*param->value_size_total = slen;
8628474SJose.Borrego@Sun.COM 
8638474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
8648474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
8658474SJose.Borrego@Sun.COM }
8668474SJose.Borrego@Sun.COM 
8678474SJose.Borrego@Sun.COM /*
8688474SJose.Borrego@Sun.COM  * Lookup a name in the registry and return the associated value.
8698474SJose.Borrego@Sun.COM  * Our registry is a case-insensitive, name-value pair table.
8708474SJose.Borrego@Sun.COM  *
8718474SJose.Borrego@Sun.COM  * Windows ProductType: WinNT, ServerNT, LanmanNT.
8728474SJose.Borrego@Sun.COM  *	Windows NT4.0 workstation: WinNT
8738474SJose.Borrego@Sun.COM  *	Windows NT4.0 server:      ServerNT
8748474SJose.Borrego@Sun.COM  *
8758474SJose.Borrego@Sun.COM  * If LanmanNT is used here, Windows 2000 sends LsarQueryInfoPolicy
8768474SJose.Borrego@Sun.COM  * with info level 6, which we don't support.  If we use ServerNT
8778474SJose.Borrego@Sun.COM  * (as reported by NT4.0 Server) Windows 2000 send requests for
8788474SJose.Borrego@Sun.COM  * levels 3 and 5, which are support.
8798474SJose.Borrego@Sun.COM  *
8808474SJose.Borrego@Sun.COM  * On success, returns a pointer to the value.  Otherwise returns
8818474SJose.Borrego@Sun.COM  * a null pointer.
8828474SJose.Borrego@Sun.COM  */
8838474SJose.Borrego@Sun.COM static char *
8848474SJose.Borrego@Sun.COM winreg_lookup_value(const char *name)
8858474SJose.Borrego@Sun.COM {
8868474SJose.Borrego@Sun.COM 	static struct registry {
8878474SJose.Borrego@Sun.COM 		char *name;
8888474SJose.Borrego@Sun.COM 		char *value;
8898474SJose.Borrego@Sun.COM 	} registry[] = {
89010504SKeyur.Desai@Sun.COM 		{ "CurrentVersion", "4.0" },
8918474SJose.Borrego@Sun.COM 		{ "ProductType", "ServerNT" },
8928474SJose.Borrego@Sun.COM 		{ "Sources",	 NULL }	/* product name */
8938474SJose.Borrego@Sun.COM 	};
8948474SJose.Borrego@Sun.COM 
8958474SJose.Borrego@Sun.COM 	int i;
8968474SJose.Borrego@Sun.COM 
8978474SJose.Borrego@Sun.COM 	for (i = 0; i < sizeof (registry)/sizeof (registry[0]); ++i) {
8988474SJose.Borrego@Sun.COM 		if (strcasecmp(registry[i].name, name) == 0) {
8998474SJose.Borrego@Sun.COM 			if (registry[i].value == NULL)
9008474SJose.Borrego@Sun.COM 				return (winreg_sysname);
9018474SJose.Borrego@Sun.COM 			else
9028474SJose.Borrego@Sun.COM 				return (registry[i].value);
9038474SJose.Borrego@Sun.COM 		}
9048474SJose.Borrego@Sun.COM 	}
9058474SJose.Borrego@Sun.COM 
9068474SJose.Borrego@Sun.COM 	return (NULL);
9078474SJose.Borrego@Sun.COM }
9088474SJose.Borrego@Sun.COM 
9098474SJose.Borrego@Sun.COM /*
9108474SJose.Borrego@Sun.COM  * winreg_s_SetKeySec
9118474SJose.Borrego@Sun.COM  */
9128474SJose.Borrego@Sun.COM /*ARGSUSED*/
9138474SJose.Borrego@Sun.COM static int
9148474SJose.Borrego@Sun.COM winreg_s_SetKeySec(void *arg, ndr_xa_t *mxa)
9158474SJose.Borrego@Sun.COM {
9168474SJose.Borrego@Sun.COM 	struct winreg_SetKeySec *param = arg;
9178474SJose.Borrego@Sun.COM 
9188474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
9198474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
9208474SJose.Borrego@Sun.COM }
9218474SJose.Borrego@Sun.COM 
9228474SJose.Borrego@Sun.COM /*
9238474SJose.Borrego@Sun.COM  * winreg_s_CreateValue
9248474SJose.Borrego@Sun.COM  */
9258474SJose.Borrego@Sun.COM /*ARGSUSED*/
9268474SJose.Borrego@Sun.COM static int
9278474SJose.Borrego@Sun.COM winreg_s_CreateValue(void *arg, ndr_xa_t *mxa)
9288474SJose.Borrego@Sun.COM {
9298474SJose.Borrego@Sun.COM 	struct winreg_CreateValue *param = arg;
9308474SJose.Borrego@Sun.COM 
9318474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
9328474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
9338474SJose.Borrego@Sun.COM }
9348474SJose.Borrego@Sun.COM 
9358474SJose.Borrego@Sun.COM /*
9368474SJose.Borrego@Sun.COM  * winreg_s_Shutdown
9378474SJose.Borrego@Sun.COM  *
9388474SJose.Borrego@Sun.COM  * Attempt to shutdown or reboot the system: access denied.
9398474SJose.Borrego@Sun.COM  */
9408474SJose.Borrego@Sun.COM /*ARGSUSED*/
9418474SJose.Borrego@Sun.COM static int
9428474SJose.Borrego@Sun.COM winreg_s_Shutdown(void *arg, ndr_xa_t *mxa)
9438474SJose.Borrego@Sun.COM {
9448474SJose.Borrego@Sun.COM 	struct winreg_Shutdown *param = arg;
9458474SJose.Borrego@Sun.COM 
9468474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
9478474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
9488474SJose.Borrego@Sun.COM }
9498474SJose.Borrego@Sun.COM 
9508474SJose.Borrego@Sun.COM /*
9518474SJose.Borrego@Sun.COM  * winreg_s_AbortShutdown
9528474SJose.Borrego@Sun.COM  *
9538474SJose.Borrego@Sun.COM  * Abort a shutdown request.
9548474SJose.Borrego@Sun.COM  */
9558474SJose.Borrego@Sun.COM static int
9568474SJose.Borrego@Sun.COM winreg_s_AbortShutdown(void *arg, ndr_xa_t *mxa)
9578474SJose.Borrego@Sun.COM {
9588474SJose.Borrego@Sun.COM 	struct winreg_AbortShutdown *param = arg;
9598474SJose.Borrego@Sun.COM 
9608474SJose.Borrego@Sun.COM 	if (ndr_is_admin(mxa))
9618474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
9628474SJose.Borrego@Sun.COM 	else
9638474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
9648474SJose.Borrego@Sun.COM 
9658474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
9668474SJose.Borrego@Sun.COM }
9678474SJose.Borrego@Sun.COM 
9688474SJose.Borrego@Sun.COM /*
9698474SJose.Borrego@Sun.COM  * winreg_s_GetVersion
9708474SJose.Borrego@Sun.COM  *
9718474SJose.Borrego@Sun.COM  * Return the windows registry version.  The current version is 5.
9728474SJose.Borrego@Sun.COM  * This call is usually made prior to enumerating or querying registry
9738474SJose.Borrego@Sun.COM  * keys or values.
9748474SJose.Borrego@Sun.COM  */
9758474SJose.Borrego@Sun.COM /*ARGSUSED*/
9768474SJose.Borrego@Sun.COM static int
9778474SJose.Borrego@Sun.COM winreg_s_GetVersion(void *arg, ndr_xa_t *mxa)
9788474SJose.Borrego@Sun.COM {
9798474SJose.Borrego@Sun.COM 	struct winreg_GetVersion *param = arg;
9808474SJose.Borrego@Sun.COM 
9818474SJose.Borrego@Sun.COM 	param->version = 5;
9828474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
9838474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
9848474SJose.Borrego@Sun.COM }
985