xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/winreg_svc.c (revision 10966:37e5dcdf36d3)
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 /*
228474SJose.Borrego@Sun.COM  * Copyright 2009 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 *);
978474SJose.Borrego@Sun.COM 
988670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCR(void *, ndr_xa_t *);
998670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCU(void *, ndr_xa_t *);
1008474SJose.Borrego@Sun.COM static int winreg_s_OpenHKLM(void *, ndr_xa_t *);
1018670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPD(void *, ndr_xa_t *);
1028670SJose.Borrego@Sun.COM static int winreg_s_OpenHKU(void *, ndr_xa_t *);
1038670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCC(void *, ndr_xa_t *);
1048670SJose.Borrego@Sun.COM static int winreg_s_OpenHKDD(void *, ndr_xa_t *);
1058670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPT(void *, ndr_xa_t *);
1068670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPN(void *, ndr_xa_t *);
1078670SJose.Borrego@Sun.COM static int winreg_s_OpenHK(void *, ndr_xa_t *, const char *);
1088474SJose.Borrego@Sun.COM static int winreg_s_Close(void *, ndr_xa_t *);
1098474SJose.Borrego@Sun.COM static int winreg_s_CreateKey(void *, ndr_xa_t *);
1108474SJose.Borrego@Sun.COM static int winreg_s_DeleteKey(void *, ndr_xa_t *);
1118474SJose.Borrego@Sun.COM static int winreg_s_DeleteValue(void *, ndr_xa_t *);
1128474SJose.Borrego@Sun.COM static int winreg_s_EnumKey(void *, ndr_xa_t *);
1138474SJose.Borrego@Sun.COM static int winreg_s_EnumValue(void *, ndr_xa_t *);
1148474SJose.Borrego@Sun.COM static int winreg_s_FlushKey(void *, ndr_xa_t *);
1158474SJose.Borrego@Sun.COM static int winreg_s_GetKeySec(void *, ndr_xa_t *);
1168474SJose.Borrego@Sun.COM static int winreg_s_NotifyChange(void *, ndr_xa_t *);
1178474SJose.Borrego@Sun.COM static int winreg_s_OpenKey(void *, ndr_xa_t *);
1188474SJose.Borrego@Sun.COM static int winreg_s_QueryKey(void *, ndr_xa_t *);
1198474SJose.Borrego@Sun.COM static int winreg_s_QueryValue(void *, ndr_xa_t *);
1208474SJose.Borrego@Sun.COM static int winreg_s_SetKeySec(void *, ndr_xa_t *);
1218474SJose.Borrego@Sun.COM static int winreg_s_CreateValue(void *, ndr_xa_t *);
1228474SJose.Borrego@Sun.COM static int winreg_s_Shutdown(void *, ndr_xa_t *);
1238474SJose.Borrego@Sun.COM static int winreg_s_AbortShutdown(void *, ndr_xa_t *);
1248474SJose.Borrego@Sun.COM static int winreg_s_GetVersion(void *, ndr_xa_t *);
1258474SJose.Borrego@Sun.COM 
1268474SJose.Borrego@Sun.COM static ndr_stub_table_t winreg_stub_table[] = {
1278670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKCR,	WINREG_OPNUM_OpenHKCR },
1288670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKCU,	WINREG_OPNUM_OpenHKCU },
1298474SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKLM,	WINREG_OPNUM_OpenHKLM },
1308670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKPD,	WINREG_OPNUM_OpenHKPD },
1318670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKU,	WINREG_OPNUM_OpenHKUsers },
1328474SJose.Borrego@Sun.COM 	{ winreg_s_Close,	WINREG_OPNUM_Close },
1338474SJose.Borrego@Sun.COM 	{ winreg_s_CreateKey,	WINREG_OPNUM_CreateKey },
1348474SJose.Borrego@Sun.COM 	{ winreg_s_DeleteKey,	WINREG_OPNUM_DeleteKey },
1358474SJose.Borrego@Sun.COM 	{ winreg_s_DeleteValue,	WINREG_OPNUM_DeleteValue },
1368474SJose.Borrego@Sun.COM 	{ winreg_s_EnumKey,	WINREG_OPNUM_EnumKey },
1378474SJose.Borrego@Sun.COM 	{ winreg_s_EnumValue,	WINREG_OPNUM_EnumValue },
1388474SJose.Borrego@Sun.COM 	{ winreg_s_FlushKey,	WINREG_OPNUM_FlushKey },
1398474SJose.Borrego@Sun.COM 	{ winreg_s_GetKeySec,	WINREG_OPNUM_GetKeySec },
1408474SJose.Borrego@Sun.COM 	{ winreg_s_NotifyChange,	WINREG_OPNUM_NotifyChange },
1418474SJose.Borrego@Sun.COM 	{ winreg_s_OpenKey,	WINREG_OPNUM_OpenKey },
1428474SJose.Borrego@Sun.COM 	{ winreg_s_QueryKey,	WINREG_OPNUM_QueryKey },
1438474SJose.Borrego@Sun.COM 	{ winreg_s_QueryValue,	WINREG_OPNUM_QueryValue },
1448474SJose.Borrego@Sun.COM 	{ winreg_s_SetKeySec,	WINREG_OPNUM_SetKeySec },
1458474SJose.Borrego@Sun.COM 	{ winreg_s_CreateValue,	WINREG_OPNUM_CreateValue },
1468474SJose.Borrego@Sun.COM 	{ winreg_s_Shutdown,	WINREG_OPNUM_Shutdown },
1478474SJose.Borrego@Sun.COM 	{ winreg_s_AbortShutdown,	WINREG_OPNUM_AbortShutdown },
1488474SJose.Borrego@Sun.COM 	{ winreg_s_GetVersion,	WINREG_OPNUM_GetVersion },
1498670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKCC,	WINREG_OPNUM_OpenHKCC },
1508670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKDD,	WINREG_OPNUM_OpenHKDD },
1518670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKPT,	WINREG_OPNUM_OpenHKPT },
1528670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKPN,	WINREG_OPNUM_OpenHKPN },
1538474SJose.Borrego@Sun.COM 	{0}
1548474SJose.Borrego@Sun.COM };
1558474SJose.Borrego@Sun.COM 
1568474SJose.Borrego@Sun.COM static ndr_service_t winreg_service = {
1578474SJose.Borrego@Sun.COM 	"Winreg",			/* name */
1588474SJose.Borrego@Sun.COM 	"Windows Registry",		/* desc */
1598474SJose.Borrego@Sun.COM 	"\\winreg",			/* endpoint */
1608474SJose.Borrego@Sun.COM 	PIPE_WINREG,			/* sec_addr_port */
1618474SJose.Borrego@Sun.COM 	"338cd001-2244-31f1-aaaa-900038001003", 1,	/* abstract */
1628474SJose.Borrego@Sun.COM 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
1638474SJose.Borrego@Sun.COM 	0,				/* no bind_instance_size */
1648474SJose.Borrego@Sun.COM 	0,				/* no bind_req() */
1658474SJose.Borrego@Sun.COM 	0,				/* no unbind_and_close() */
1668474SJose.Borrego@Sun.COM 	0,				/* use generic_call_stub() */
1678474SJose.Borrego@Sun.COM 	&TYPEINFO(winreg_interface),	/* interface ti */
1688474SJose.Borrego@Sun.COM 	winreg_stub_table		/* stub_table */
1698474SJose.Borrego@Sun.COM };
1708474SJose.Borrego@Sun.COM 
1718474SJose.Borrego@Sun.COM static char winreg_sysname[SYS_NMLN];
1728474SJose.Borrego@Sun.COM 
1738474SJose.Borrego@Sun.COM /*
1748474SJose.Borrego@Sun.COM  * winreg_initialize
1758474SJose.Borrego@Sun.COM  *
1768474SJose.Borrego@Sun.COM  * Initialize and register the WINREG RPC interface with the RPC runtime
1778474SJose.Borrego@Sun.COM  * library. It must be called in order to use either the client side
1788474SJose.Borrego@Sun.COM  * or the server side functions.
1798474SJose.Borrego@Sun.COM  */
1808474SJose.Borrego@Sun.COM void
1818474SJose.Borrego@Sun.COM winreg_initialize(void)
1828474SJose.Borrego@Sun.COM {
1838474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
1848474SJose.Borrego@Sun.COM 	struct utsname name;
1858474SJose.Borrego@Sun.COM 	char *sysname;
1868474SJose.Borrego@Sun.COM 	int i;
1878474SJose.Borrego@Sun.COM 
1888474SJose.Borrego@Sun.COM 	list_create(&winreg_keylist.kl_list, sizeof (winreg_subkey_t),
1898474SJose.Borrego@Sun.COM 	    offsetof(winreg_subkey_t, sk_lnd));
1908474SJose.Borrego@Sun.COM 	winreg_keylist.kl_count = 0;
1918474SJose.Borrego@Sun.COM 
1928474SJose.Borrego@Sun.COM 	for (i = 0; i < sizeof (winreg_keys)/sizeof (winreg_keys[0]); ++i) {
1938474SJose.Borrego@Sun.COM 		if ((key = malloc(sizeof (winreg_subkey_t))) != NULL) {
1948474SJose.Borrego@Sun.COM 			bzero(key, sizeof (winreg_subkey_t));
1958474SJose.Borrego@Sun.COM 			(void) strlcpy(key->sk_name, winreg_keys[i],
1968474SJose.Borrego@Sun.COM 			    MAXPATHLEN);
1978474SJose.Borrego@Sun.COM 			key->sk_predefined = B_TRUE;
1988474SJose.Borrego@Sun.COM 			list_insert_tail(&winreg_keylist.kl_list, key);
1998474SJose.Borrego@Sun.COM 			++winreg_keylist.kl_count;
2008474SJose.Borrego@Sun.COM 		}
2018474SJose.Borrego@Sun.COM 	}
2028474SJose.Borrego@Sun.COM 
2038474SJose.Borrego@Sun.COM 	if (uname(&name) < 0)
2048474SJose.Borrego@Sun.COM 		sysname = "Solaris";
2058474SJose.Borrego@Sun.COM 	else
2068474SJose.Borrego@Sun.COM 		sysname = name.sysname;
2078474SJose.Borrego@Sun.COM 
2088474SJose.Borrego@Sun.COM 	(void) strlcpy(winreg_sysname, sysname, SYS_NMLN);
2098474SJose.Borrego@Sun.COM 	(void) ndr_svc_register(&winreg_service);
2108474SJose.Borrego@Sun.COM }
2118474SJose.Borrego@Sun.COM 
2128670SJose.Borrego@Sun.COM static int
2138670SJose.Borrego@Sun.COM winreg_s_OpenHKCR(void *arg, ndr_xa_t *mxa)
2148670SJose.Borrego@Sun.COM {
2158670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKCR"));
2168670SJose.Borrego@Sun.COM }
2178670SJose.Borrego@Sun.COM 
2188474SJose.Borrego@Sun.COM static int
2198670SJose.Borrego@Sun.COM winreg_s_OpenHKCU(void *arg, ndr_xa_t *mxa)
2208670SJose.Borrego@Sun.COM {
2218670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKCU"));
2228670SJose.Borrego@Sun.COM }
2238670SJose.Borrego@Sun.COM 
2248670SJose.Borrego@Sun.COM static int
2258670SJose.Borrego@Sun.COM winreg_s_OpenHKLM(void *arg, ndr_xa_t *mxa)
2268670SJose.Borrego@Sun.COM {
2278670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKLM"));
2288670SJose.Borrego@Sun.COM }
2298670SJose.Borrego@Sun.COM 
2308670SJose.Borrego@Sun.COM static int
2318670SJose.Borrego@Sun.COM winreg_s_OpenHKPD(void *arg, ndr_xa_t *mxa)
2328474SJose.Borrego@Sun.COM {
2338670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKPD"));
2348670SJose.Borrego@Sun.COM }
2358670SJose.Borrego@Sun.COM 
2368670SJose.Borrego@Sun.COM static int
2378670SJose.Borrego@Sun.COM winreg_s_OpenHKU(void *arg, ndr_xa_t *mxa)
2388670SJose.Borrego@Sun.COM {
2398670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKU"));
2408670SJose.Borrego@Sun.COM }
2418670SJose.Borrego@Sun.COM 
2428670SJose.Borrego@Sun.COM static int
2438670SJose.Borrego@Sun.COM winreg_s_OpenHKCC(void *arg, ndr_xa_t *mxa)
2448670SJose.Borrego@Sun.COM {
2458670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKCC"));
2468670SJose.Borrego@Sun.COM }
2478474SJose.Borrego@Sun.COM 
2488670SJose.Borrego@Sun.COM static int
2498670SJose.Borrego@Sun.COM winreg_s_OpenHKDD(void *arg, ndr_xa_t *mxa)
2508670SJose.Borrego@Sun.COM {
2518670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKDD"));
2528670SJose.Borrego@Sun.COM }
2538474SJose.Borrego@Sun.COM 
2548670SJose.Borrego@Sun.COM static int
2558670SJose.Borrego@Sun.COM winreg_s_OpenHKPT(void *arg, ndr_xa_t *mxa)
2568670SJose.Borrego@Sun.COM {
2578670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKPT"));
2588670SJose.Borrego@Sun.COM }
2598670SJose.Borrego@Sun.COM 
2608670SJose.Borrego@Sun.COM static int
2618670SJose.Borrego@Sun.COM winreg_s_OpenHKPN(void *arg, ndr_xa_t *mxa)
2628670SJose.Borrego@Sun.COM {
2638670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKPN"));
2648474SJose.Borrego@Sun.COM }
2658474SJose.Borrego@Sun.COM 
2668474SJose.Borrego@Sun.COM /*
2678670SJose.Borrego@Sun.COM  * winreg_s_OpenHK
2688474SJose.Borrego@Sun.COM  *
2698670SJose.Borrego@Sun.COM  * Common code to open root HKEYs.
2708474SJose.Borrego@Sun.COM  */
2718474SJose.Borrego@Sun.COM static int
2728670SJose.Borrego@Sun.COM winreg_s_OpenHK(void *arg, ndr_xa_t *mxa, const char *hkey)
2738474SJose.Borrego@Sun.COM {
2748670SJose.Borrego@Sun.COM 	struct winreg_OpenHKCR *param = arg;
2758474SJose.Borrego@Sun.COM 	ndr_hdid_t *id;
2768670SJose.Borrego@Sun.COM 	char *dupkey;
2778474SJose.Borrego@Sun.COM 
2788670SJose.Borrego@Sun.COM 	if ((dupkey = strdup(hkey)) == NULL) {
2798474SJose.Borrego@Sun.COM 		bzero(&param->handle, sizeof (winreg_handle_t));
2808670SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
2818670SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
2828474SJose.Borrego@Sun.COM 	}
2838474SJose.Borrego@Sun.COM 
2848670SJose.Borrego@Sun.COM 	if ((id = ndr_hdalloc(mxa, dupkey)) == NULL) {
2858670SJose.Borrego@Sun.COM 		free(dupkey);
2868474SJose.Borrego@Sun.COM 		bzero(&param->handle, sizeof (winreg_handle_t));
2878474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
2888474SJose.Borrego@Sun.COM 	} else {
2898474SJose.Borrego@Sun.COM 		bcopy(id, &param->handle, sizeof (winreg_handle_t));
2908474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
2918474SJose.Borrego@Sun.COM 	}
2928474SJose.Borrego@Sun.COM 
2938474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
2948474SJose.Borrego@Sun.COM }
2958474SJose.Borrego@Sun.COM 
2968474SJose.Borrego@Sun.COM /*
2978474SJose.Borrego@Sun.COM  * winreg_s_Close
2988474SJose.Borrego@Sun.COM  *
2998474SJose.Borrego@Sun.COM  * This is a request to close the WINREG interface specified by the
3008474SJose.Borrego@Sun.COM  * handle. We don't track handles (yet), so just zero out the handle
3018474SJose.Borrego@Sun.COM  * and return NDR_DRC_OK. Setting the handle to zero appears to be
3028474SJose.Borrego@Sun.COM  * standard behaviour.
3038474SJose.Borrego@Sun.COM  */
3048474SJose.Borrego@Sun.COM static int
3058474SJose.Borrego@Sun.COM winreg_s_Close(void *arg, ndr_xa_t *mxa)
3068474SJose.Borrego@Sun.COM {
3078474SJose.Borrego@Sun.COM 	struct winreg_Close *param = arg;
3088474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
3098670SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
3108670SJose.Borrego@Sun.COM 
3118670SJose.Borrego@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
3128670SJose.Borrego@Sun.COM 		free(hd->nh_data);
3138670SJose.Borrego@Sun.COM 		hd->nh_data = NULL;
3148670SJose.Borrego@Sun.COM 	}
3158474SJose.Borrego@Sun.COM 
3168474SJose.Borrego@Sun.COM 	ndr_hdfree(mxa, id);
3178474SJose.Borrego@Sun.COM 
3188474SJose.Borrego@Sun.COM 	bzero(&param->result_handle, sizeof (winreg_handle_t));
3198474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
3208474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
3218474SJose.Borrego@Sun.COM }
3228474SJose.Borrego@Sun.COM 
3238474SJose.Borrego@Sun.COM /*
3248474SJose.Borrego@Sun.COM  * winreg_s_CreateKey
3258474SJose.Borrego@Sun.COM  */
3268474SJose.Borrego@Sun.COM static int
3278474SJose.Borrego@Sun.COM winreg_s_CreateKey(void *arg, ndr_xa_t *mxa)
3288474SJose.Borrego@Sun.COM {
3298474SJose.Borrego@Sun.COM 	struct winreg_CreateKey *param = arg;
3308474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
3318474SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
3328474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
3338474SJose.Borrego@Sun.COM 	char *subkey;
3348670SJose.Borrego@Sun.COM 	char *dupkey;
3358474SJose.Borrego@Sun.COM 	DWORD *action;
3368474SJose.Borrego@Sun.COM 
3378474SJose.Borrego@Sun.COM 	subkey = (char *)param->subkey.str;
3388474SJose.Borrego@Sun.COM 
3398474SJose.Borrego@Sun.COM 	if (!ndr_is_admin(mxa) || (subkey == NULL)) {
3408474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
3418474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
3428474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
3438474SJose.Borrego@Sun.COM 	}
3448474SJose.Borrego@Sun.COM 
3458474SJose.Borrego@Sun.COM 	hd = ndr_hdlookup(mxa, id);
3468474SJose.Borrego@Sun.COM 	if (hd == NULL) {
3478474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
3488474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
3498474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
3508474SJose.Borrego@Sun.COM 	}
3518474SJose.Borrego@Sun.COM 
3528474SJose.Borrego@Sun.COM 	if ((action = NDR_NEW(mxa, DWORD)) == NULL) {
3538474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
3548474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
3558474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
3568474SJose.Borrego@Sun.COM 	}
3578474SJose.Borrego@Sun.COM 
3588474SJose.Borrego@Sun.COM 	if (list_is_empty(&winreg_keylist.kl_list))
3598474SJose.Borrego@Sun.COM 		goto new_key;
3608474SJose.Borrego@Sun.COM 
3618474SJose.Borrego@Sun.COM 	/*
3628474SJose.Borrego@Sun.COM 	 * Check for an existing key.
3638474SJose.Borrego@Sun.COM 	 */
3648474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
3658474SJose.Borrego@Sun.COM 	do {
3668474SJose.Borrego@Sun.COM 		if (strcasecmp(subkey, key->sk_name) == 0) {
3678474SJose.Borrego@Sun.COM 			bcopy(&key->sk_handle, &param->result_handle,
3688474SJose.Borrego@Sun.COM 			    sizeof (winreg_handle_t));
3698474SJose.Borrego@Sun.COM 			*action = WINREG_ACTION_EXISTING_KEY;
3708474SJose.Borrego@Sun.COM 			param->action = action;
3718474SJose.Borrego@Sun.COM 			param->status = ERROR_SUCCESS;
3728474SJose.Borrego@Sun.COM 			return (NDR_DRC_OK);
3738474SJose.Borrego@Sun.COM 		}
3748474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
3758474SJose.Borrego@Sun.COM 
3768474SJose.Borrego@Sun.COM new_key:
3778474SJose.Borrego@Sun.COM 	/*
3788474SJose.Borrego@Sun.COM 	 * Create a new key.
3798474SJose.Borrego@Sun.COM 	 */
3808670SJose.Borrego@Sun.COM 	if ((dupkey = strdup(subkey)) == NULL) {
3818670SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
3828670SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
3838670SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
3848670SJose.Borrego@Sun.COM 	}
3858670SJose.Borrego@Sun.COM 
3868670SJose.Borrego@Sun.COM 	id = ndr_hdalloc(mxa, dupkey);
3878474SJose.Borrego@Sun.COM 	key = malloc(sizeof (winreg_subkey_t));
3888474SJose.Borrego@Sun.COM 
3898474SJose.Borrego@Sun.COM 	if ((id == NULL) || (key == NULL)) {
3908670SJose.Borrego@Sun.COM 		free(dupkey);
3918474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
3928474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
3938474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
3948474SJose.Borrego@Sun.COM 	}
3958474SJose.Borrego@Sun.COM 
3968474SJose.Borrego@Sun.COM 	bcopy(id, &key->sk_handle, sizeof (ndr_hdid_t));
3978474SJose.Borrego@Sun.COM 	(void) strlcpy(key->sk_name, subkey, MAXPATHLEN);
3988474SJose.Borrego@Sun.COM 	key->sk_predefined = B_FALSE;
3998474SJose.Borrego@Sun.COM 	list_insert_tail(&winreg_keylist.kl_list, key);
4008474SJose.Borrego@Sun.COM 	++winreg_keylist.kl_count;
4018474SJose.Borrego@Sun.COM 
4028474SJose.Borrego@Sun.COM 	bcopy(id, &param->result_handle, sizeof (winreg_handle_t));
4038474SJose.Borrego@Sun.COM 	*action = WINREG_ACTION_NEW_KEY;
4048474SJose.Borrego@Sun.COM 	param->action = action;
4058474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
4068474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
4078474SJose.Borrego@Sun.COM }
4088474SJose.Borrego@Sun.COM 
4098474SJose.Borrego@Sun.COM /*
4108474SJose.Borrego@Sun.COM  * winreg_s_DeleteKey
4118474SJose.Borrego@Sun.COM  */
4128474SJose.Borrego@Sun.COM static int
4138474SJose.Borrego@Sun.COM winreg_s_DeleteKey(void *arg, ndr_xa_t *mxa)
4148474SJose.Borrego@Sun.COM {
4158474SJose.Borrego@Sun.COM 	struct winreg_DeleteKey *param = arg;
4168474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
4178670SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
4188474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
4198474SJose.Borrego@Sun.COM 	char *subkey;
4208474SJose.Borrego@Sun.COM 
4218474SJose.Borrego@Sun.COM 	subkey = (char *)param->subkey.str;
4228474SJose.Borrego@Sun.COM 
4238474SJose.Borrego@Sun.COM 	if (!ndr_is_admin(mxa) || (subkey == NULL)) {
4248474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
4258474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
4268474SJose.Borrego@Sun.COM 	}
4278474SJose.Borrego@Sun.COM 
4288474SJose.Borrego@Sun.COM 	if ((ndr_hdlookup(mxa, id) == NULL) ||
4298474SJose.Borrego@Sun.COM 	    list_is_empty(&winreg_keylist.kl_list) ||
4308474SJose.Borrego@Sun.COM 	    winreg_key_has_subkey(subkey)) {
4318474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
4328474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
4338474SJose.Borrego@Sun.COM 	}
4348474SJose.Borrego@Sun.COM 
4358474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
4368474SJose.Borrego@Sun.COM 	do {
4378474SJose.Borrego@Sun.COM 		if (strcasecmp(subkey, key->sk_name) == 0) {
4388474SJose.Borrego@Sun.COM 			if (key->sk_predefined == B_TRUE) {
4398474SJose.Borrego@Sun.COM 				/* Predefined keys cannot be deleted */
4408474SJose.Borrego@Sun.COM 				break;
4418474SJose.Borrego@Sun.COM 			}
4428474SJose.Borrego@Sun.COM 
4438474SJose.Borrego@Sun.COM 			list_remove(&winreg_keylist.kl_list, key);
4448474SJose.Borrego@Sun.COM 			--winreg_keylist.kl_count;
4458670SJose.Borrego@Sun.COM 
4468670SJose.Borrego@Sun.COM 			hd = ndr_hdlookup(mxa, &key->sk_handle);
4478670SJose.Borrego@Sun.COM 			if (hd != NULL) {
4488670SJose.Borrego@Sun.COM 				free(hd->nh_data);
4498670SJose.Borrego@Sun.COM 				hd->nh_data = NULL;
4508670SJose.Borrego@Sun.COM 			}
4518670SJose.Borrego@Sun.COM 
4528474SJose.Borrego@Sun.COM 			ndr_hdfree(mxa, &key->sk_handle);
4538474SJose.Borrego@Sun.COM 			free(key);
4548474SJose.Borrego@Sun.COM 			param->status = ERROR_SUCCESS;
4558474SJose.Borrego@Sun.COM 			return (NDR_DRC_OK);
4568474SJose.Borrego@Sun.COM 		}
4578474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
4588474SJose.Borrego@Sun.COM 
4598474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
4608474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
4618474SJose.Borrego@Sun.COM }
4628474SJose.Borrego@Sun.COM 
4638474SJose.Borrego@Sun.COM static boolean_t
4648474SJose.Borrego@Sun.COM winreg_key_has_subkey(const char *subkey)
4658474SJose.Borrego@Sun.COM {
4668474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
4678474SJose.Borrego@Sun.COM 	int keylen;
4688474SJose.Borrego@Sun.COM 
4698474SJose.Borrego@Sun.COM 	if (list_is_empty(&winreg_keylist.kl_list))
4708474SJose.Borrego@Sun.COM 		return (B_FALSE);
4718474SJose.Borrego@Sun.COM 
4728474SJose.Borrego@Sun.COM 	keylen = strlen(subkey);
4738474SJose.Borrego@Sun.COM 
4748474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
4758474SJose.Borrego@Sun.COM 	do {
4768474SJose.Borrego@Sun.COM 		if (strncasecmp(subkey, key->sk_name, keylen) == 0) {
4778474SJose.Borrego@Sun.COM 			/*
4788474SJose.Borrego@Sun.COM 			 * Potential match.  If sk_name is longer than
4798474SJose.Borrego@Sun.COM 			 * subkey, then sk_name is a subkey of our key.
4808474SJose.Borrego@Sun.COM 			 */
4818474SJose.Borrego@Sun.COM 			if (keylen < strlen(key->sk_name))
4828474SJose.Borrego@Sun.COM 				return (B_TRUE);
4838474SJose.Borrego@Sun.COM 		}
4848474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
4858474SJose.Borrego@Sun.COM 
4868474SJose.Borrego@Sun.COM 	return (B_FALSE);
4878474SJose.Borrego@Sun.COM }
4888474SJose.Borrego@Sun.COM 
4898474SJose.Borrego@Sun.COM static char *
4908670SJose.Borrego@Sun.COM winreg_enum_subkey(ndr_xa_t *mxa, const char *subkey, uint32_t index)
4918474SJose.Borrego@Sun.COM {
4928474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
4938670SJose.Borrego@Sun.COM 	char *entry;
4948670SJose.Borrego@Sun.COM 	char *p;
4958670SJose.Borrego@Sun.COM 	int subkeylen;
4968670SJose.Borrego@Sun.COM 	int count = 0;
4978474SJose.Borrego@Sun.COM 
4988474SJose.Borrego@Sun.COM 	if (subkey == NULL)
4998474SJose.Borrego@Sun.COM 		return (NULL);
5008474SJose.Borrego@Sun.COM 
5018474SJose.Borrego@Sun.COM 	if (list_is_empty(&winreg_keylist.kl_list))
5028474SJose.Borrego@Sun.COM 		return (NULL);
5038474SJose.Borrego@Sun.COM 
5048670SJose.Borrego@Sun.COM 	subkeylen = strlen(subkey);
5058670SJose.Borrego@Sun.COM 
5068670SJose.Borrego@Sun.COM 	for (key = list_head(&winreg_keylist.kl_list);
5078670SJose.Borrego@Sun.COM 	    key != NULL; key = list_next(&winreg_keylist.kl_list, key)) {
5088670SJose.Borrego@Sun.COM 		if (strncasecmp(subkey, key->sk_name, subkeylen) == 0) {
5098670SJose.Borrego@Sun.COM 			p = key->sk_name + subkeylen;
5108670SJose.Borrego@Sun.COM 
5118670SJose.Borrego@Sun.COM 			if ((*p != '\\') || (*p == '\0')) {
5128670SJose.Borrego@Sun.COM 				/*
5138670SJose.Borrego@Sun.COM 				 * Not the same subkey or an exact match.
5148670SJose.Borrego@Sun.COM 				 * We're looking for children of subkey.
5158670SJose.Borrego@Sun.COM 				 */
5168670SJose.Borrego@Sun.COM 				continue;
5178670SJose.Borrego@Sun.COM 			}
5188670SJose.Borrego@Sun.COM 
5198670SJose.Borrego@Sun.COM 			++p;
5208670SJose.Borrego@Sun.COM 
5218670SJose.Borrego@Sun.COM 			if (count < index) {
5228670SJose.Borrego@Sun.COM 				++count;
5238670SJose.Borrego@Sun.COM 				continue;
5248670SJose.Borrego@Sun.COM 			}
5258670SJose.Borrego@Sun.COM 
5268670SJose.Borrego@Sun.COM 			if ((entry = NDR_STRDUP(mxa, p)) == NULL)
5278670SJose.Borrego@Sun.COM 				return (NULL);
5288670SJose.Borrego@Sun.COM 
5298670SJose.Borrego@Sun.COM 			if ((p = strchr(entry, '\\')) != NULL)
5308670SJose.Borrego@Sun.COM 				*p = '\0';
5318670SJose.Borrego@Sun.COM 
5328670SJose.Borrego@Sun.COM 			return (entry);
5338474SJose.Borrego@Sun.COM 		}
5348670SJose.Borrego@Sun.COM 	}
5358474SJose.Borrego@Sun.COM 
5368474SJose.Borrego@Sun.COM 	return (NULL);
5378474SJose.Borrego@Sun.COM }
5388474SJose.Borrego@Sun.COM 
5398474SJose.Borrego@Sun.COM /*
5408474SJose.Borrego@Sun.COM  * winreg_s_DeleteValue
5418474SJose.Borrego@Sun.COM  */
5428474SJose.Borrego@Sun.COM /*ARGSUSED*/
5438474SJose.Borrego@Sun.COM static int
5448474SJose.Borrego@Sun.COM winreg_s_DeleteValue(void *arg, ndr_xa_t *mxa)
5458474SJose.Borrego@Sun.COM {
5468474SJose.Borrego@Sun.COM 	struct winreg_DeleteValue *param = arg;
5478474SJose.Borrego@Sun.COM 
5488474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
5498474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
5508474SJose.Borrego@Sun.COM }
5518474SJose.Borrego@Sun.COM 
5528474SJose.Borrego@Sun.COM /*
5538474SJose.Borrego@Sun.COM  * winreg_s_EnumKey
5548474SJose.Borrego@Sun.COM  */
5558474SJose.Borrego@Sun.COM static int
5568474SJose.Borrego@Sun.COM winreg_s_EnumKey(void *arg, ndr_xa_t *mxa)
5578474SJose.Borrego@Sun.COM {
5588474SJose.Borrego@Sun.COM 	struct winreg_EnumKey *param = arg;
5598474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
5608670SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
5618670SJose.Borrego@Sun.COM 	char *subkey;
5628670SJose.Borrego@Sun.COM 	char *name = NULL;
5638474SJose.Borrego@Sun.COM 
5648670SJose.Borrego@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) != NULL)
5658670SJose.Borrego@Sun.COM 		name = hd->nh_data;
5668474SJose.Borrego@Sun.COM 
5678670SJose.Borrego@Sun.COM 	if (hd == NULL || name == NULL) {
5688474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumKey));
5698474SJose.Borrego@Sun.COM 		param->status = ERROR_NO_MORE_ITEMS;
5708474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5718474SJose.Borrego@Sun.COM 	}
5728474SJose.Borrego@Sun.COM 
5738670SJose.Borrego@Sun.COM 	subkey = winreg_enum_subkey(mxa, name, param->index);
5748670SJose.Borrego@Sun.COM 	if (subkey == NULL) {
5758474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumKey));
5768670SJose.Borrego@Sun.COM 		param->status = ERROR_NO_MORE_ITEMS;
5778474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5788474SJose.Borrego@Sun.COM 	}
5798474SJose.Borrego@Sun.COM 
5808670SJose.Borrego@Sun.COM 	if (NDR_MSTRING(mxa, subkey, (ndr_mstring_t *)&param->name_out) == -1) {
5818474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumKey));
5828474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
5838474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
5848474SJose.Borrego@Sun.COM 	}
5858670SJose.Borrego@Sun.COM 	/*
5868670SJose.Borrego@Sun.COM 	 * This request requires that the length includes the null.
5878670SJose.Borrego@Sun.COM 	 */
5888670SJose.Borrego@Sun.COM 	param->name_out.length = param->name_out.allosize;
5898474SJose.Borrego@Sun.COM 
5908474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
5918474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
5928474SJose.Borrego@Sun.COM }
5938474SJose.Borrego@Sun.COM 
5948474SJose.Borrego@Sun.COM /*
5958474SJose.Borrego@Sun.COM  * winreg_s_EnumValue
5968474SJose.Borrego@Sun.COM  */
5978474SJose.Borrego@Sun.COM static int
5988474SJose.Borrego@Sun.COM winreg_s_EnumValue(void *arg, ndr_xa_t *mxa)
5998474SJose.Borrego@Sun.COM {
6008474SJose.Borrego@Sun.COM 	struct winreg_EnumValue *param = arg;
6018474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
6028474SJose.Borrego@Sun.COM 
6038474SJose.Borrego@Sun.COM 	if (ndr_hdlookup(mxa, id) == NULL) {
6048474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumValue));
6058474SJose.Borrego@Sun.COM 		param->status = ERROR_NO_MORE_ITEMS;
6068474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6078474SJose.Borrego@Sun.COM 	}
6088474SJose.Borrego@Sun.COM 
6098474SJose.Borrego@Sun.COM 	bzero(param, sizeof (struct winreg_EnumValue));
6108474SJose.Borrego@Sun.COM 	param->status = ERROR_NO_MORE_ITEMS;
6118474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6128474SJose.Borrego@Sun.COM }
6138474SJose.Borrego@Sun.COM 
6148474SJose.Borrego@Sun.COM /*
6158474SJose.Borrego@Sun.COM  * winreg_s_FlushKey
6168474SJose.Borrego@Sun.COM  *
6178474SJose.Borrego@Sun.COM  * Flush the attributes associated with the specified open key to disk.
6188474SJose.Borrego@Sun.COM  */
6198474SJose.Borrego@Sun.COM static int
6208474SJose.Borrego@Sun.COM winreg_s_FlushKey(void *arg, ndr_xa_t *mxa)
6218474SJose.Borrego@Sun.COM {
6228474SJose.Borrego@Sun.COM 	struct winreg_FlushKey *param = arg;
6238474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
6248474SJose.Borrego@Sun.COM 
6258474SJose.Borrego@Sun.COM 	if (ndr_hdlookup(mxa, id) == NULL)
6268474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
6278474SJose.Borrego@Sun.COM 	else
6288474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
6298474SJose.Borrego@Sun.COM 
6308474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6318474SJose.Borrego@Sun.COM }
6328474SJose.Borrego@Sun.COM 
6338474SJose.Borrego@Sun.COM /*
6348474SJose.Borrego@Sun.COM  * winreg_s_GetKeySec
6358474SJose.Borrego@Sun.COM  */
6368474SJose.Borrego@Sun.COM /*ARGSUSED*/
6378474SJose.Borrego@Sun.COM static int
6388474SJose.Borrego@Sun.COM winreg_s_GetKeySec(void *arg, ndr_xa_t *mxa)
6398474SJose.Borrego@Sun.COM {
6408474SJose.Borrego@Sun.COM 	struct winreg_GetKeySec *param = arg;
6418474SJose.Borrego@Sun.COM 
6428474SJose.Borrego@Sun.COM 	bzero(param, sizeof (struct winreg_GetKeySec));
6438474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
6448474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6458474SJose.Borrego@Sun.COM }
6468474SJose.Borrego@Sun.COM 
6478474SJose.Borrego@Sun.COM /*
6488474SJose.Borrego@Sun.COM  * winreg_s_NotifyChange
6498474SJose.Borrego@Sun.COM  */
6508474SJose.Borrego@Sun.COM static int
6518474SJose.Borrego@Sun.COM winreg_s_NotifyChange(void *arg, ndr_xa_t *mxa)
6528474SJose.Borrego@Sun.COM {
6538474SJose.Borrego@Sun.COM 	struct winreg_NotifyChange *param = arg;
6548474SJose.Borrego@Sun.COM 
6558474SJose.Borrego@Sun.COM 	if (ndr_is_admin(mxa))
6568474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
6578474SJose.Borrego@Sun.COM 	else
6588474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
6598474SJose.Borrego@Sun.COM 
6608474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6618474SJose.Borrego@Sun.COM }
6628474SJose.Borrego@Sun.COM 
6638474SJose.Borrego@Sun.COM /*
6648474SJose.Borrego@Sun.COM  * winreg_s_OpenKey
6658474SJose.Borrego@Sun.COM  *
6668474SJose.Borrego@Sun.COM  * This is a request to open a windows registry key.
6678474SJose.Borrego@Sun.COM  * If we recognize the key, we return a handle.
6688474SJose.Borrego@Sun.COM  *
6698474SJose.Borrego@Sun.COM  * Returns:
6708474SJose.Borrego@Sun.COM  *	ERROR_SUCCESS		Valid handle returned.
6718474SJose.Borrego@Sun.COM  *	ERROR_FILE_NOT_FOUND	No key or unable to allocate a handle.
6728474SJose.Borrego@Sun.COM  */
6738474SJose.Borrego@Sun.COM static int
6748474SJose.Borrego@Sun.COM winreg_s_OpenKey(void *arg, ndr_xa_t *mxa)
6758474SJose.Borrego@Sun.COM {
6768474SJose.Borrego@Sun.COM 	struct winreg_OpenKey *param = arg;
6779914Samw@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
6789914Samw@Sun.COM 	ndr_handle_t *hd;
6798474SJose.Borrego@Sun.COM 	char *subkey = (char *)param->name.str;
6808474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
6818670SJose.Borrego@Sun.COM 	char *dupkey;
6828474SJose.Borrego@Sun.COM 
6839914Samw@Sun.COM 	if (subkey == NULL || *subkey == '\0') {
6849914Samw@Sun.COM 		if ((hd = ndr_hdlookup(mxa, id)) != NULL)
6859914Samw@Sun.COM 			subkey = hd->nh_data;
6869914Samw@Sun.COM 	}
6879914Samw@Sun.COM 
6889914Samw@Sun.COM 	id = NULL;
6899914Samw@Sun.COM 
6908670SJose.Borrego@Sun.COM 	if (subkey == NULL || list_is_empty(&winreg_keylist.kl_list)) {
6918474SJose.Borrego@Sun.COM 		bzero(&param->result_handle, sizeof (winreg_handle_t));
6928474SJose.Borrego@Sun.COM 		param->status = ERROR_FILE_NOT_FOUND;
6938474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6948474SJose.Borrego@Sun.COM 	}
6958474SJose.Borrego@Sun.COM 
6968474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
6978474SJose.Borrego@Sun.COM 	do {
6988474SJose.Borrego@Sun.COM 		if (strcasecmp(subkey, key->sk_name) == 0) {
6998670SJose.Borrego@Sun.COM 			if (key->sk_predefined == B_TRUE) {
7008670SJose.Borrego@Sun.COM 				if ((dupkey = strdup(subkey)) == NULL)
7018670SJose.Borrego@Sun.COM 					break;
7028670SJose.Borrego@Sun.COM 
7038670SJose.Borrego@Sun.COM 				id = ndr_hdalloc(mxa, dupkey);
7048670SJose.Borrego@Sun.COM 				if (id == NULL)
7058670SJose.Borrego@Sun.COM 					free(dupkey);
7068670SJose.Borrego@Sun.COM 			} else {
7078474SJose.Borrego@Sun.COM 				id = &key->sk_handle;
7088670SJose.Borrego@Sun.COM 			}
7098474SJose.Borrego@Sun.COM 
7108474SJose.Borrego@Sun.COM 			if (id == NULL)
7118474SJose.Borrego@Sun.COM 				break;
7128474SJose.Borrego@Sun.COM 
7138474SJose.Borrego@Sun.COM 			bcopy(id, &param->result_handle,
7148474SJose.Borrego@Sun.COM 			    sizeof (winreg_handle_t));
7158474SJose.Borrego@Sun.COM 			param->status = ERROR_SUCCESS;
7168474SJose.Borrego@Sun.COM 			return (NDR_DRC_OK);
7178474SJose.Borrego@Sun.COM 		}
7188474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
7198474SJose.Borrego@Sun.COM 
7208474SJose.Borrego@Sun.COM 	bzero(&param->result_handle, sizeof (winreg_handle_t));
7218474SJose.Borrego@Sun.COM 	param->status = ERROR_FILE_NOT_FOUND;
7228474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
7238474SJose.Borrego@Sun.COM }
7248474SJose.Borrego@Sun.COM 
7258474SJose.Borrego@Sun.COM /*
7268474SJose.Borrego@Sun.COM  * winreg_s_QueryKey
7278474SJose.Borrego@Sun.COM  */
7288474SJose.Borrego@Sun.COM /*ARGSUSED*/
7298474SJose.Borrego@Sun.COM static int
7308474SJose.Borrego@Sun.COM winreg_s_QueryKey(void *arg, ndr_xa_t *mxa)
7318474SJose.Borrego@Sun.COM {
7328474SJose.Borrego@Sun.COM 	struct winreg_QueryKey *param = arg;
7338474SJose.Borrego@Sun.COM 	int rc;
7348474SJose.Borrego@Sun.COM 	winreg_string_t	*name;
7358474SJose.Borrego@Sun.COM 
7368474SJose.Borrego@Sun.COM 	name = (winreg_string_t	*)&param->name;
7378474SJose.Borrego@Sun.COM 	bzero(param, sizeof (struct winreg_QueryKey));
7388474SJose.Borrego@Sun.COM 	if ((name = NDR_NEW(mxa, winreg_string_t)) != NULL)
7398474SJose.Borrego@Sun.COM 		rc = NDR_MSTRING(mxa, "", (ndr_mstring_t *)name);
7408474SJose.Borrego@Sun.COM 
7418474SJose.Borrego@Sun.COM 	if ((name == NULL) || (rc != 0)) {
7428474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_QueryKey));
7438474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
7448474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
7458474SJose.Borrego@Sun.COM 	}
7468474SJose.Borrego@Sun.COM 
7478474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
7488474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
7498474SJose.Borrego@Sun.COM }
7508474SJose.Borrego@Sun.COM 
7518474SJose.Borrego@Sun.COM /*
7528474SJose.Borrego@Sun.COM  * winreg_s_QueryValue
7538474SJose.Borrego@Sun.COM  *
7548474SJose.Borrego@Sun.COM  * This is a request to get the value associated with a specified name.
7558474SJose.Borrego@Sun.COM  *
7568474SJose.Borrego@Sun.COM  * Returns:
7578474SJose.Borrego@Sun.COM  *	ERROR_SUCCESS		Value returned.
7588474SJose.Borrego@Sun.COM  *	ERROR_FILE_NOT_FOUND	PrimaryModule is not supported.
7598474SJose.Borrego@Sun.COM  *	ERROR_CANTREAD          No such name or memory problem.
7608474SJose.Borrego@Sun.COM  */
7618474SJose.Borrego@Sun.COM static int
7628474SJose.Borrego@Sun.COM winreg_s_QueryValue(void *arg, ndr_xa_t *mxa)
7638474SJose.Borrego@Sun.COM {
7648474SJose.Borrego@Sun.COM 	struct winreg_QueryValue *param = arg;
7658474SJose.Borrego@Sun.COM 	struct winreg_value *pv;
7668474SJose.Borrego@Sun.COM 	char *name;
7678474SJose.Borrego@Sun.COM 	char *value;
7688474SJose.Borrego@Sun.COM 	DWORD slen;
7698474SJose.Borrego@Sun.COM 	DWORD msize;
7708474SJose.Borrego@Sun.COM 
7718474SJose.Borrego@Sun.COM 	name = (char *)param->value_name.str;
7728474SJose.Borrego@Sun.COM 
7738474SJose.Borrego@Sun.COM 	if (strcasecmp(name, "PrimaryModule") == 0) {
7748474SJose.Borrego@Sun.COM 		param->status = ERROR_FILE_NOT_FOUND;
7758474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
7768474SJose.Borrego@Sun.COM 	}
7778474SJose.Borrego@Sun.COM 
7788474SJose.Borrego@Sun.COM 	if ((value = winreg_lookup_value(name)) == NULL) {
7798474SJose.Borrego@Sun.COM 		param->status = ERROR_CANTREAD;
7808474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
7818474SJose.Borrego@Sun.COM 	}
7828474SJose.Borrego@Sun.COM 
783*10966SJordan.Brown@Sun.COM 	slen = smb_wcequiv_strlen(value) + sizeof (smb_wchar_t);
7848474SJose.Borrego@Sun.COM 	msize = sizeof (struct winreg_value) + slen;
7858474SJose.Borrego@Sun.COM 
7868474SJose.Borrego@Sun.COM 	param->value = (struct winreg_value *)NDR_MALLOC(mxa, msize);
7878474SJose.Borrego@Sun.COM 	param->type = NDR_NEW(mxa, DWORD);
7888474SJose.Borrego@Sun.COM 	param->value_size = NDR_NEW(mxa, DWORD);
7898474SJose.Borrego@Sun.COM 	param->value_size_total = NDR_NEW(mxa, DWORD);
7908474SJose.Borrego@Sun.COM 
7918474SJose.Borrego@Sun.COM 	if (param->value == NULL || param->type == NULL ||
7928474SJose.Borrego@Sun.COM 	    param->value_size == NULL || param->value_size_total == NULL) {
7938474SJose.Borrego@Sun.COM 		param->status = ERROR_CANTREAD;
7948474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
7958474SJose.Borrego@Sun.COM 	}
7968474SJose.Borrego@Sun.COM 
7978474SJose.Borrego@Sun.COM 	bzero(param->value, msize);
7988474SJose.Borrego@Sun.COM 	pv = param->value;
7998474SJose.Borrego@Sun.COM 	pv->vc_first_is = 0;
8008474SJose.Borrego@Sun.COM 	pv->vc_length_is = slen;
8018474SJose.Borrego@Sun.COM 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
802*10966SJordan.Brown@Sun.COM 	(void) ndr_mbstowcs(NULL, (smb_wchar_t *)pv->value, value, slen);
8038474SJose.Borrego@Sun.COM 
8048474SJose.Borrego@Sun.COM 	*param->type = 1;
8058474SJose.Borrego@Sun.COM 	*param->value_size = slen;
8068474SJose.Borrego@Sun.COM 	*param->value_size_total = slen;
8078474SJose.Borrego@Sun.COM 
8088474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
8098474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
8108474SJose.Borrego@Sun.COM }
8118474SJose.Borrego@Sun.COM 
8128474SJose.Borrego@Sun.COM /*
8138474SJose.Borrego@Sun.COM  * Lookup a name in the registry and return the associated value.
8148474SJose.Borrego@Sun.COM  * Our registry is a case-insensitive, name-value pair table.
8158474SJose.Borrego@Sun.COM  *
8168474SJose.Borrego@Sun.COM  * Windows ProductType: WinNT, ServerNT, LanmanNT.
8178474SJose.Borrego@Sun.COM  *	Windows NT4.0 workstation: WinNT
8188474SJose.Borrego@Sun.COM  *	Windows NT4.0 server:      ServerNT
8198474SJose.Borrego@Sun.COM  *
8208474SJose.Borrego@Sun.COM  * If LanmanNT is used here, Windows 2000 sends LsarQueryInfoPolicy
8218474SJose.Borrego@Sun.COM  * with info level 6, which we don't support.  If we use ServerNT
8228474SJose.Borrego@Sun.COM  * (as reported by NT4.0 Server) Windows 2000 send requests for
8238474SJose.Borrego@Sun.COM  * levels 3 and 5, which are support.
8248474SJose.Borrego@Sun.COM  *
8258474SJose.Borrego@Sun.COM  * On success, returns a pointer to the value.  Otherwise returns
8268474SJose.Borrego@Sun.COM  * a null pointer.
8278474SJose.Borrego@Sun.COM  */
8288474SJose.Borrego@Sun.COM static char *
8298474SJose.Borrego@Sun.COM winreg_lookup_value(const char *name)
8308474SJose.Borrego@Sun.COM {
8318474SJose.Borrego@Sun.COM 	static struct registry {
8328474SJose.Borrego@Sun.COM 		char *name;
8338474SJose.Borrego@Sun.COM 		char *value;
8348474SJose.Borrego@Sun.COM 	} registry[] = {
83510504SKeyur.Desai@Sun.COM 		{ "CurrentVersion", "4.0" },
8368474SJose.Borrego@Sun.COM 		{ "ProductType", "ServerNT" },
8378474SJose.Borrego@Sun.COM 		{ "Sources",	 NULL }	/* product name */
8388474SJose.Borrego@Sun.COM 	};
8398474SJose.Borrego@Sun.COM 
8408474SJose.Borrego@Sun.COM 	int i;
8418474SJose.Borrego@Sun.COM 
8428474SJose.Borrego@Sun.COM 	for (i = 0; i < sizeof (registry)/sizeof (registry[0]); ++i) {
8438474SJose.Borrego@Sun.COM 		if (strcasecmp(registry[i].name, name) == 0) {
8448474SJose.Borrego@Sun.COM 			if (registry[i].value == NULL)
8458474SJose.Borrego@Sun.COM 				return (winreg_sysname);
8468474SJose.Borrego@Sun.COM 			else
8478474SJose.Borrego@Sun.COM 				return (registry[i].value);
8488474SJose.Borrego@Sun.COM 		}
8498474SJose.Borrego@Sun.COM 	}
8508474SJose.Borrego@Sun.COM 
8518474SJose.Borrego@Sun.COM 	return (NULL);
8528474SJose.Borrego@Sun.COM }
8538474SJose.Borrego@Sun.COM 
8548474SJose.Borrego@Sun.COM /*
8558474SJose.Borrego@Sun.COM  * winreg_s_SetKeySec
8568474SJose.Borrego@Sun.COM  */
8578474SJose.Borrego@Sun.COM /*ARGSUSED*/
8588474SJose.Borrego@Sun.COM static int
8598474SJose.Borrego@Sun.COM winreg_s_SetKeySec(void *arg, ndr_xa_t *mxa)
8608474SJose.Borrego@Sun.COM {
8618474SJose.Borrego@Sun.COM 	struct winreg_SetKeySec *param = arg;
8628474SJose.Borrego@Sun.COM 
8638474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
8648474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
8658474SJose.Borrego@Sun.COM }
8668474SJose.Borrego@Sun.COM 
8678474SJose.Borrego@Sun.COM /*
8688474SJose.Borrego@Sun.COM  * winreg_s_CreateValue
8698474SJose.Borrego@Sun.COM  */
8708474SJose.Borrego@Sun.COM /*ARGSUSED*/
8718474SJose.Borrego@Sun.COM static int
8728474SJose.Borrego@Sun.COM winreg_s_CreateValue(void *arg, ndr_xa_t *mxa)
8738474SJose.Borrego@Sun.COM {
8748474SJose.Borrego@Sun.COM 	struct winreg_CreateValue *param = arg;
8758474SJose.Borrego@Sun.COM 
8768474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
8778474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
8788474SJose.Borrego@Sun.COM }
8798474SJose.Borrego@Sun.COM 
8808474SJose.Borrego@Sun.COM /*
8818474SJose.Borrego@Sun.COM  * winreg_s_Shutdown
8828474SJose.Borrego@Sun.COM  *
8838474SJose.Borrego@Sun.COM  * Attempt to shutdown or reboot the system: access denied.
8848474SJose.Borrego@Sun.COM  */
8858474SJose.Borrego@Sun.COM /*ARGSUSED*/
8868474SJose.Borrego@Sun.COM static int
8878474SJose.Borrego@Sun.COM winreg_s_Shutdown(void *arg, ndr_xa_t *mxa)
8888474SJose.Borrego@Sun.COM {
8898474SJose.Borrego@Sun.COM 	struct winreg_Shutdown *param = arg;
8908474SJose.Borrego@Sun.COM 
8918474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
8928474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
8938474SJose.Borrego@Sun.COM }
8948474SJose.Borrego@Sun.COM 
8958474SJose.Borrego@Sun.COM /*
8968474SJose.Borrego@Sun.COM  * winreg_s_AbortShutdown
8978474SJose.Borrego@Sun.COM  *
8988474SJose.Borrego@Sun.COM  * Abort a shutdown request.
8998474SJose.Borrego@Sun.COM  */
9008474SJose.Borrego@Sun.COM static int
9018474SJose.Borrego@Sun.COM winreg_s_AbortShutdown(void *arg, ndr_xa_t *mxa)
9028474SJose.Borrego@Sun.COM {
9038474SJose.Borrego@Sun.COM 	struct winreg_AbortShutdown *param = arg;
9048474SJose.Borrego@Sun.COM 
9058474SJose.Borrego@Sun.COM 	if (ndr_is_admin(mxa))
9068474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
9078474SJose.Borrego@Sun.COM 	else
9088474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
9098474SJose.Borrego@Sun.COM 
9108474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
9118474SJose.Borrego@Sun.COM }
9128474SJose.Borrego@Sun.COM 
9138474SJose.Borrego@Sun.COM /*
9148474SJose.Borrego@Sun.COM  * winreg_s_GetVersion
9158474SJose.Borrego@Sun.COM  *
9168474SJose.Borrego@Sun.COM  * Return the windows registry version.  The current version is 5.
9178474SJose.Borrego@Sun.COM  * This call is usually made prior to enumerating or querying registry
9188474SJose.Borrego@Sun.COM  * keys or values.
9198474SJose.Borrego@Sun.COM  */
9208474SJose.Borrego@Sun.COM /*ARGSUSED*/
9218474SJose.Borrego@Sun.COM static int
9228474SJose.Borrego@Sun.COM winreg_s_GetVersion(void *arg, ndr_xa_t *mxa)
9238474SJose.Borrego@Sun.COM {
9248474SJose.Borrego@Sun.COM 	struct winreg_GetVersion *param = arg;
9258474SJose.Borrego@Sun.COM 
9268474SJose.Borrego@Sun.COM 	param->version = 5;
9278474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
9288474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
9298474SJose.Borrego@Sun.COM }
930