xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/winreg_svc.c (revision 11963:061945695ce1)
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 /*
2211447Samw@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",
71*11963SAfshin.Ardakani@Sun.COM 	"SunOS",
72*11963SAfshin.Ardakani@Sun.COM 	"Solaris",
738474SJose.Borrego@Sun.COM 	"System\\CurrentControlSet\\Services\\Eventlog",
748670SJose.Borrego@Sun.COM 	"System\\CurrentControlSet\\Services\\Eventlog\\Application",
75*11963SAfshin.Ardakani@Sun.COM 	"System\\CurrentControlSet\\Services\\Eventlog\\"
76*11963SAfshin.Ardakani@Sun.COM 						"Application\\Application",
778670SJose.Borrego@Sun.COM 	"System\\CurrentControlSet\\Services\\Eventlog\\Security",
78*11963SAfshin.Ardakani@Sun.COM 	"System\\CurrentControlSet\\Services\\Eventlog\\Security\\Security",
798474SJose.Borrego@Sun.COM 	"System\\CurrentControlSet\\Services\\Eventlog\\System",
80*11963SAfshin.Ardakani@Sun.COM 	"System\\CurrentControlSet\\Services\\Eventlog\\System\\System",
818474SJose.Borrego@Sun.COM 	"System\\CurrentControlSet\\Control\\ProductOptions",
829914Samw@Sun.COM 	"SOFTWARE",
838474SJose.Borrego@Sun.COM 	"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
848474SJose.Borrego@Sun.COM };
858474SJose.Borrego@Sun.COM 
868474SJose.Borrego@Sun.COM typedef struct winreg_subkey {
878474SJose.Borrego@Sun.COM 	list_node_t sk_lnd;
888474SJose.Borrego@Sun.COM 	ndr_hdid_t sk_handle;
898474SJose.Borrego@Sun.COM 	char sk_name[MAXPATHLEN];
908474SJose.Borrego@Sun.COM 	boolean_t sk_predefined;
918474SJose.Borrego@Sun.COM } winreg_subkey_t;
928474SJose.Borrego@Sun.COM 
938474SJose.Borrego@Sun.COM typedef struct winreg_keylist {
948474SJose.Borrego@Sun.COM 	list_t kl_list;
958474SJose.Borrego@Sun.COM 	int kl_count;
968474SJose.Borrego@Sun.COM } winreg_keylist_t;
978474SJose.Borrego@Sun.COM 
988474SJose.Borrego@Sun.COM static winreg_keylist_t winreg_keylist;
99*11963SAfshin.Ardakani@Sun.COM static mutex_t winreg_mutex;
1008474SJose.Borrego@Sun.COM 
101*11963SAfshin.Ardakani@Sun.COM static ndr_hdid_t *winreg_alloc_id(ndr_xa_t *, const char *);
102*11963SAfshin.Ardakani@Sun.COM static void winreg_dealloc_id(ndr_xa_t *, ndr_hdid_t *);
1038474SJose.Borrego@Sun.COM static boolean_t winreg_key_has_subkey(const char *);
1048670SJose.Borrego@Sun.COM static char *winreg_enum_subkey(ndr_xa_t *, const char *, uint32_t);
1058474SJose.Borrego@Sun.COM static char *winreg_lookup_value(const char *);
10611447Samw@Sun.COM static uint32_t winreg_sd_format(smb_sd_t *);
10711447Samw@Sun.COM uint32_t srvsvc_sd_set_relative(smb_sd_t *, uint8_t *);
1088474SJose.Borrego@Sun.COM 
1098670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCR(void *, ndr_xa_t *);
1108670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCU(void *, ndr_xa_t *);
1118474SJose.Borrego@Sun.COM static int winreg_s_OpenHKLM(void *, ndr_xa_t *);
1128670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPD(void *, ndr_xa_t *);
1138670SJose.Borrego@Sun.COM static int winreg_s_OpenHKU(void *, ndr_xa_t *);
1148670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCC(void *, ndr_xa_t *);
1158670SJose.Borrego@Sun.COM static int winreg_s_OpenHKDD(void *, ndr_xa_t *);
1168670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPT(void *, ndr_xa_t *);
1178670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPN(void *, ndr_xa_t *);
1188670SJose.Borrego@Sun.COM static int winreg_s_OpenHK(void *, ndr_xa_t *, const char *);
1198474SJose.Borrego@Sun.COM static int winreg_s_Close(void *, ndr_xa_t *);
1208474SJose.Borrego@Sun.COM static int winreg_s_CreateKey(void *, ndr_xa_t *);
1218474SJose.Borrego@Sun.COM static int winreg_s_DeleteKey(void *, ndr_xa_t *);
1228474SJose.Borrego@Sun.COM static int winreg_s_DeleteValue(void *, ndr_xa_t *);
1238474SJose.Borrego@Sun.COM static int winreg_s_EnumKey(void *, ndr_xa_t *);
1248474SJose.Borrego@Sun.COM static int winreg_s_EnumValue(void *, ndr_xa_t *);
1258474SJose.Borrego@Sun.COM static int winreg_s_FlushKey(void *, ndr_xa_t *);
1268474SJose.Borrego@Sun.COM static int winreg_s_GetKeySec(void *, ndr_xa_t *);
1278474SJose.Borrego@Sun.COM static int winreg_s_NotifyChange(void *, ndr_xa_t *);
1288474SJose.Borrego@Sun.COM static int winreg_s_OpenKey(void *, ndr_xa_t *);
1298474SJose.Borrego@Sun.COM static int winreg_s_QueryKey(void *, ndr_xa_t *);
1308474SJose.Borrego@Sun.COM static int winreg_s_QueryValue(void *, ndr_xa_t *);
1318474SJose.Borrego@Sun.COM static int winreg_s_SetKeySec(void *, ndr_xa_t *);
1328474SJose.Borrego@Sun.COM static int winreg_s_CreateValue(void *, ndr_xa_t *);
1338474SJose.Borrego@Sun.COM static int winreg_s_Shutdown(void *, ndr_xa_t *);
1348474SJose.Borrego@Sun.COM static int winreg_s_AbortShutdown(void *, ndr_xa_t *);
1358474SJose.Borrego@Sun.COM static int winreg_s_GetVersion(void *, ndr_xa_t *);
1368474SJose.Borrego@Sun.COM 
1378474SJose.Borrego@Sun.COM static ndr_stub_table_t winreg_stub_table[] = {
1388670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKCR,	WINREG_OPNUM_OpenHKCR },
1398670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKCU,	WINREG_OPNUM_OpenHKCU },
1408474SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKLM,	WINREG_OPNUM_OpenHKLM },
1418670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKPD,	WINREG_OPNUM_OpenHKPD },
1428670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKU,	WINREG_OPNUM_OpenHKUsers },
1438474SJose.Borrego@Sun.COM 	{ winreg_s_Close,	WINREG_OPNUM_Close },
1448474SJose.Borrego@Sun.COM 	{ winreg_s_CreateKey,	WINREG_OPNUM_CreateKey },
1458474SJose.Borrego@Sun.COM 	{ winreg_s_DeleteKey,	WINREG_OPNUM_DeleteKey },
1468474SJose.Borrego@Sun.COM 	{ winreg_s_DeleteValue,	WINREG_OPNUM_DeleteValue },
1478474SJose.Borrego@Sun.COM 	{ winreg_s_EnumKey,	WINREG_OPNUM_EnumKey },
1488474SJose.Borrego@Sun.COM 	{ winreg_s_EnumValue,	WINREG_OPNUM_EnumValue },
1498474SJose.Borrego@Sun.COM 	{ winreg_s_FlushKey,	WINREG_OPNUM_FlushKey },
1508474SJose.Borrego@Sun.COM 	{ winreg_s_GetKeySec,	WINREG_OPNUM_GetKeySec },
1518474SJose.Borrego@Sun.COM 	{ winreg_s_NotifyChange,	WINREG_OPNUM_NotifyChange },
1528474SJose.Borrego@Sun.COM 	{ winreg_s_OpenKey,	WINREG_OPNUM_OpenKey },
1538474SJose.Borrego@Sun.COM 	{ winreg_s_QueryKey,	WINREG_OPNUM_QueryKey },
1548474SJose.Borrego@Sun.COM 	{ winreg_s_QueryValue,	WINREG_OPNUM_QueryValue },
1558474SJose.Borrego@Sun.COM 	{ winreg_s_SetKeySec,	WINREG_OPNUM_SetKeySec },
1568474SJose.Borrego@Sun.COM 	{ winreg_s_CreateValue,	WINREG_OPNUM_CreateValue },
1578474SJose.Borrego@Sun.COM 	{ winreg_s_Shutdown,	WINREG_OPNUM_Shutdown },
1588474SJose.Borrego@Sun.COM 	{ winreg_s_AbortShutdown,	WINREG_OPNUM_AbortShutdown },
1598474SJose.Borrego@Sun.COM 	{ winreg_s_GetVersion,	WINREG_OPNUM_GetVersion },
1608670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKCC,	WINREG_OPNUM_OpenHKCC },
1618670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKDD,	WINREG_OPNUM_OpenHKDD },
1628670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKPT,	WINREG_OPNUM_OpenHKPT },
1638670SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKPN,	WINREG_OPNUM_OpenHKPN },
1648474SJose.Borrego@Sun.COM 	{0}
1658474SJose.Borrego@Sun.COM };
1668474SJose.Borrego@Sun.COM 
1678474SJose.Borrego@Sun.COM static ndr_service_t winreg_service = {
1688474SJose.Borrego@Sun.COM 	"Winreg",			/* name */
1698474SJose.Borrego@Sun.COM 	"Windows Registry",		/* desc */
1708474SJose.Borrego@Sun.COM 	"\\winreg",			/* endpoint */
1718474SJose.Borrego@Sun.COM 	PIPE_WINREG,			/* sec_addr_port */
1728474SJose.Borrego@Sun.COM 	"338cd001-2244-31f1-aaaa-900038001003", 1,	/* abstract */
1738474SJose.Borrego@Sun.COM 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
1748474SJose.Borrego@Sun.COM 	0,				/* no bind_instance_size */
1758474SJose.Borrego@Sun.COM 	0,				/* no bind_req() */
1768474SJose.Borrego@Sun.COM 	0,				/* no unbind_and_close() */
1778474SJose.Borrego@Sun.COM 	0,				/* use generic_call_stub() */
1788474SJose.Borrego@Sun.COM 	&TYPEINFO(winreg_interface),	/* interface ti */
1798474SJose.Borrego@Sun.COM 	winreg_stub_table		/* stub_table */
1808474SJose.Borrego@Sun.COM };
1818474SJose.Borrego@Sun.COM 
1828474SJose.Borrego@Sun.COM static char winreg_sysname[SYS_NMLN];
183*11963SAfshin.Ardakani@Sun.COM static char winreg_sysver[SMB_VERSTR_LEN];
1848474SJose.Borrego@Sun.COM 
1858474SJose.Borrego@Sun.COM /*
1868474SJose.Borrego@Sun.COM  * winreg_initialize
1878474SJose.Borrego@Sun.COM  *
1888474SJose.Borrego@Sun.COM  * Initialize and register the WINREG RPC interface with the RPC runtime
1898474SJose.Borrego@Sun.COM  * library. It must be called in order to use either the client side
1908474SJose.Borrego@Sun.COM  * or the server side functions.
1918474SJose.Borrego@Sun.COM  */
1928474SJose.Borrego@Sun.COM void
1938474SJose.Borrego@Sun.COM winreg_initialize(void)
1948474SJose.Borrego@Sun.COM {
1958474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
196*11963SAfshin.Ardakani@Sun.COM 	smb_version_t version;
1978474SJose.Borrego@Sun.COM 	struct utsname name;
1988474SJose.Borrego@Sun.COM 	char *sysname;
1998474SJose.Borrego@Sun.COM 	int i;
2008474SJose.Borrego@Sun.COM 
201*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&winreg_mutex);
202*11963SAfshin.Ardakani@Sun.COM 
2038474SJose.Borrego@Sun.COM 	list_create(&winreg_keylist.kl_list, sizeof (winreg_subkey_t),
2048474SJose.Borrego@Sun.COM 	    offsetof(winreg_subkey_t, sk_lnd));
2058474SJose.Borrego@Sun.COM 	winreg_keylist.kl_count = 0;
2068474SJose.Borrego@Sun.COM 
2078474SJose.Borrego@Sun.COM 	for (i = 0; i < sizeof (winreg_keys)/sizeof (winreg_keys[0]); ++i) {
2088474SJose.Borrego@Sun.COM 		if ((key = malloc(sizeof (winreg_subkey_t))) != NULL) {
2098474SJose.Borrego@Sun.COM 			bzero(key, sizeof (winreg_subkey_t));
2108474SJose.Borrego@Sun.COM 			(void) strlcpy(key->sk_name, winreg_keys[i],
2118474SJose.Borrego@Sun.COM 			    MAXPATHLEN);
2128474SJose.Borrego@Sun.COM 			key->sk_predefined = B_TRUE;
213*11963SAfshin.Ardakani@Sun.COM 
2148474SJose.Borrego@Sun.COM 			list_insert_tail(&winreg_keylist.kl_list, key);
2158474SJose.Borrego@Sun.COM 			++winreg_keylist.kl_count;
2168474SJose.Borrego@Sun.COM 		}
2178474SJose.Borrego@Sun.COM 	}
2188474SJose.Borrego@Sun.COM 
219*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&winreg_mutex);
220*11963SAfshin.Ardakani@Sun.COM 
2218474SJose.Borrego@Sun.COM 	if (uname(&name) < 0)
2228474SJose.Borrego@Sun.COM 		sysname = "Solaris";
2238474SJose.Borrego@Sun.COM 	else
2248474SJose.Borrego@Sun.COM 		sysname = name.sysname;
2258474SJose.Borrego@Sun.COM 
2268474SJose.Borrego@Sun.COM 	(void) strlcpy(winreg_sysname, sysname, SYS_NMLN);
227*11963SAfshin.Ardakani@Sun.COM 
228*11963SAfshin.Ardakani@Sun.COM 	smb_config_get_version(&version);
229*11963SAfshin.Ardakani@Sun.COM 	(void) snprintf(winreg_sysver, SMB_VERSTR_LEN, "%d.%d",
230*11963SAfshin.Ardakani@Sun.COM 	    version.sv_major, version.sv_minor);
231*11963SAfshin.Ardakani@Sun.COM 
2328474SJose.Borrego@Sun.COM 	(void) ndr_svc_register(&winreg_service);
2338474SJose.Borrego@Sun.COM }
2348474SJose.Borrego@Sun.COM 
2358670SJose.Borrego@Sun.COM static int
2368670SJose.Borrego@Sun.COM winreg_s_OpenHKCR(void *arg, ndr_xa_t *mxa)
2378670SJose.Borrego@Sun.COM {
2388670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKCR"));
2398670SJose.Borrego@Sun.COM }
2408670SJose.Borrego@Sun.COM 
2418474SJose.Borrego@Sun.COM static int
2428670SJose.Borrego@Sun.COM winreg_s_OpenHKCU(void *arg, ndr_xa_t *mxa)
2438670SJose.Borrego@Sun.COM {
2448670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKCU"));
2458670SJose.Borrego@Sun.COM }
2468670SJose.Borrego@Sun.COM 
2478670SJose.Borrego@Sun.COM static int
2488670SJose.Borrego@Sun.COM winreg_s_OpenHKLM(void *arg, ndr_xa_t *mxa)
2498670SJose.Borrego@Sun.COM {
2508670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKLM"));
2518670SJose.Borrego@Sun.COM }
2528670SJose.Borrego@Sun.COM 
2538670SJose.Borrego@Sun.COM static int
2548670SJose.Borrego@Sun.COM winreg_s_OpenHKPD(void *arg, ndr_xa_t *mxa)
2558474SJose.Borrego@Sun.COM {
2568670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKPD"));
2578670SJose.Borrego@Sun.COM }
2588670SJose.Borrego@Sun.COM 
2598670SJose.Borrego@Sun.COM static int
2608670SJose.Borrego@Sun.COM winreg_s_OpenHKU(void *arg, ndr_xa_t *mxa)
2618670SJose.Borrego@Sun.COM {
2628670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKU"));
2638670SJose.Borrego@Sun.COM }
2648670SJose.Borrego@Sun.COM 
2658670SJose.Borrego@Sun.COM static int
2668670SJose.Borrego@Sun.COM winreg_s_OpenHKCC(void *arg, ndr_xa_t *mxa)
2678670SJose.Borrego@Sun.COM {
2688670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKCC"));
2698670SJose.Borrego@Sun.COM }
2708474SJose.Borrego@Sun.COM 
2718670SJose.Borrego@Sun.COM static int
2728670SJose.Borrego@Sun.COM winreg_s_OpenHKDD(void *arg, ndr_xa_t *mxa)
2738670SJose.Borrego@Sun.COM {
2748670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKDD"));
2758670SJose.Borrego@Sun.COM }
2768474SJose.Borrego@Sun.COM 
2778670SJose.Borrego@Sun.COM static int
2788670SJose.Borrego@Sun.COM winreg_s_OpenHKPT(void *arg, ndr_xa_t *mxa)
2798670SJose.Borrego@Sun.COM {
2808670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKPT"));
2818670SJose.Borrego@Sun.COM }
2828670SJose.Borrego@Sun.COM 
2838670SJose.Borrego@Sun.COM static int
2848670SJose.Borrego@Sun.COM winreg_s_OpenHKPN(void *arg, ndr_xa_t *mxa)
2858670SJose.Borrego@Sun.COM {
2868670SJose.Borrego@Sun.COM 	return (winreg_s_OpenHK(arg, mxa, "HKPN"));
2878474SJose.Borrego@Sun.COM }
2888474SJose.Borrego@Sun.COM 
2898474SJose.Borrego@Sun.COM /*
2908670SJose.Borrego@Sun.COM  * winreg_s_OpenHK
2918474SJose.Borrego@Sun.COM  *
2928670SJose.Borrego@Sun.COM  * Common code to open root HKEYs.
2938474SJose.Borrego@Sun.COM  */
2948474SJose.Borrego@Sun.COM static int
2958670SJose.Borrego@Sun.COM winreg_s_OpenHK(void *arg, ndr_xa_t *mxa, const char *hkey)
2968474SJose.Borrego@Sun.COM {
2978670SJose.Borrego@Sun.COM 	struct winreg_OpenHKCR *param = arg;
2988474SJose.Borrego@Sun.COM 	ndr_hdid_t *id;
2998474SJose.Borrego@Sun.COM 
300*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&winreg_mutex);
3018474SJose.Borrego@Sun.COM 
302*11963SAfshin.Ardakani@Sun.COM 	if ((id = winreg_alloc_id(mxa, hkey)) == NULL) {
3038474SJose.Borrego@Sun.COM 		bzero(&param->handle, sizeof (winreg_handle_t));
3048474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
3058474SJose.Borrego@Sun.COM 	} else {
3068474SJose.Borrego@Sun.COM 		bcopy(id, &param->handle, sizeof (winreg_handle_t));
3078474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
3088474SJose.Borrego@Sun.COM 	}
3098474SJose.Borrego@Sun.COM 
310*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&winreg_mutex);
3118474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
3128474SJose.Borrego@Sun.COM }
3138474SJose.Borrego@Sun.COM 
3148474SJose.Borrego@Sun.COM /*
3158474SJose.Borrego@Sun.COM  * winreg_s_Close
3168474SJose.Borrego@Sun.COM  *
3178474SJose.Borrego@Sun.COM  * This is a request to close the WINREG interface specified by the
3188474SJose.Borrego@Sun.COM  * handle. We don't track handles (yet), so just zero out the handle
3198474SJose.Borrego@Sun.COM  * and return NDR_DRC_OK. Setting the handle to zero appears to be
3208474SJose.Borrego@Sun.COM  * standard behaviour.
3218474SJose.Borrego@Sun.COM  */
3228474SJose.Borrego@Sun.COM static int
3238474SJose.Borrego@Sun.COM winreg_s_Close(void *arg, ndr_xa_t *mxa)
3248474SJose.Borrego@Sun.COM {
3258474SJose.Borrego@Sun.COM 	struct winreg_Close *param = arg;
3268474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
327*11963SAfshin.Ardakani@Sun.COM 
328*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&winreg_mutex);
329*11963SAfshin.Ardakani@Sun.COM 	winreg_dealloc_id(mxa, id);
330*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&winreg_mutex);
331*11963SAfshin.Ardakani@Sun.COM 
332*11963SAfshin.Ardakani@Sun.COM 	bzero(&param->result_handle, sizeof (winreg_handle_t));
333*11963SAfshin.Ardakani@Sun.COM 	param->status = ERROR_SUCCESS;
334*11963SAfshin.Ardakani@Sun.COM 	return (NDR_DRC_OK);
335*11963SAfshin.Ardakani@Sun.COM }
336*11963SAfshin.Ardakani@Sun.COM 
337*11963SAfshin.Ardakani@Sun.COM static ndr_hdid_t *
338*11963SAfshin.Ardakani@Sun.COM winreg_alloc_id(ndr_xa_t *mxa, const char *key)
339*11963SAfshin.Ardakani@Sun.COM {
340*11963SAfshin.Ardakani@Sun.COM 	ndr_handle_t	*hd;
341*11963SAfshin.Ardakani@Sun.COM 	ndr_hdid_t	*id;
342*11963SAfshin.Ardakani@Sun.COM 	char		*data;
343*11963SAfshin.Ardakani@Sun.COM 
344*11963SAfshin.Ardakani@Sun.COM 	if ((data = strdup(key)) == NULL)
345*11963SAfshin.Ardakani@Sun.COM 		return (NULL);
346*11963SAfshin.Ardakani@Sun.COM 
347*11963SAfshin.Ardakani@Sun.COM 	if ((id = ndr_hdalloc(mxa, data)) == NULL) {
348*11963SAfshin.Ardakani@Sun.COM 		free(data);
349*11963SAfshin.Ardakani@Sun.COM 		return (NULL);
350*11963SAfshin.Ardakani@Sun.COM 	}
351*11963SAfshin.Ardakani@Sun.COM 
352*11963SAfshin.Ardakani@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) != NULL)
353*11963SAfshin.Ardakani@Sun.COM 		hd->nh_data_free = free;
354*11963SAfshin.Ardakani@Sun.COM 
355*11963SAfshin.Ardakani@Sun.COM 	return (id);
356*11963SAfshin.Ardakani@Sun.COM }
357*11963SAfshin.Ardakani@Sun.COM 
358*11963SAfshin.Ardakani@Sun.COM static void
359*11963SAfshin.Ardakani@Sun.COM winreg_dealloc_id(ndr_xa_t *mxa, ndr_hdid_t *id)
360*11963SAfshin.Ardakani@Sun.COM {
3618670SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
3628670SJose.Borrego@Sun.COM 
3638670SJose.Borrego@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
3648670SJose.Borrego@Sun.COM 		free(hd->nh_data);
3658670SJose.Borrego@Sun.COM 		hd->nh_data = NULL;
3668670SJose.Borrego@Sun.COM 	}
3678474SJose.Borrego@Sun.COM 
3688474SJose.Borrego@Sun.COM 	ndr_hdfree(mxa, id);
3698474SJose.Borrego@Sun.COM }
3708474SJose.Borrego@Sun.COM 
3718474SJose.Borrego@Sun.COM /*
3728474SJose.Borrego@Sun.COM  * winreg_s_CreateKey
3738474SJose.Borrego@Sun.COM  */
3748474SJose.Borrego@Sun.COM static int
3758474SJose.Borrego@Sun.COM winreg_s_CreateKey(void *arg, ndr_xa_t *mxa)
3768474SJose.Borrego@Sun.COM {
3778474SJose.Borrego@Sun.COM 	struct winreg_CreateKey *param = arg;
3788474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
3798474SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
3808474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
3818474SJose.Borrego@Sun.COM 	char *subkey;
3828474SJose.Borrego@Sun.COM 	DWORD *action;
3838474SJose.Borrego@Sun.COM 
3848474SJose.Borrego@Sun.COM 	subkey = (char *)param->subkey.str;
3858474SJose.Borrego@Sun.COM 
3868474SJose.Borrego@Sun.COM 	if (!ndr_is_admin(mxa) || (subkey == NULL)) {
3878474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
3888474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
3898474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
3908474SJose.Borrego@Sun.COM 	}
3918474SJose.Borrego@Sun.COM 
392*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&winreg_mutex);
393*11963SAfshin.Ardakani@Sun.COM 
3948474SJose.Borrego@Sun.COM 	hd = ndr_hdlookup(mxa, id);
3958474SJose.Borrego@Sun.COM 	if (hd == NULL) {
396*11963SAfshin.Ardakani@Sun.COM 		(void) mutex_unlock(&winreg_mutex);
3978474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
3988474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
3998474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
4008474SJose.Borrego@Sun.COM 	}
4018474SJose.Borrego@Sun.COM 
4028474SJose.Borrego@Sun.COM 	if ((action = NDR_NEW(mxa, DWORD)) == NULL) {
403*11963SAfshin.Ardakani@Sun.COM 		(void) mutex_unlock(&winreg_mutex);
4048474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
4058474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
4068474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
4078474SJose.Borrego@Sun.COM 	}
4088474SJose.Borrego@Sun.COM 
4098474SJose.Borrego@Sun.COM 	if (list_is_empty(&winreg_keylist.kl_list))
4108474SJose.Borrego@Sun.COM 		goto new_key;
4118474SJose.Borrego@Sun.COM 
4128474SJose.Borrego@Sun.COM 	/*
4138474SJose.Borrego@Sun.COM 	 * Check for an existing key.
4148474SJose.Borrego@Sun.COM 	 */
4158474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
4168474SJose.Borrego@Sun.COM 	do {
4178474SJose.Borrego@Sun.COM 		if (strcasecmp(subkey, key->sk_name) == 0) {
4188474SJose.Borrego@Sun.COM 			bcopy(&key->sk_handle, &param->result_handle,
4198474SJose.Borrego@Sun.COM 			    sizeof (winreg_handle_t));
420*11963SAfshin.Ardakani@Sun.COM 
421*11963SAfshin.Ardakani@Sun.COM 			(void) mutex_unlock(&winreg_mutex);
4228474SJose.Borrego@Sun.COM 			*action = WINREG_ACTION_EXISTING_KEY;
4238474SJose.Borrego@Sun.COM 			param->action = action;
4248474SJose.Borrego@Sun.COM 			param->status = ERROR_SUCCESS;
4258474SJose.Borrego@Sun.COM 			return (NDR_DRC_OK);
4268474SJose.Borrego@Sun.COM 		}
4278474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
4288474SJose.Borrego@Sun.COM 
4298474SJose.Borrego@Sun.COM new_key:
4308474SJose.Borrego@Sun.COM 	/*
4318474SJose.Borrego@Sun.COM 	 * Create a new key.
4328474SJose.Borrego@Sun.COM 	 */
433*11963SAfshin.Ardakani@Sun.COM 	if ((id = winreg_alloc_id(mxa, subkey)) == NULL)
434*11963SAfshin.Ardakani@Sun.COM 		goto no_memory;
4358670SJose.Borrego@Sun.COM 
436*11963SAfshin.Ardakani@Sun.COM 	if ((key = malloc(sizeof (winreg_subkey_t))) == NULL) {
437*11963SAfshin.Ardakani@Sun.COM 		winreg_dealloc_id(mxa, id);
438*11963SAfshin.Ardakani@Sun.COM 		goto no_memory;
4398474SJose.Borrego@Sun.COM 	}
4408474SJose.Borrego@Sun.COM 
4418474SJose.Borrego@Sun.COM 	bcopy(id, &key->sk_handle, sizeof (ndr_hdid_t));
4428474SJose.Borrego@Sun.COM 	(void) strlcpy(key->sk_name, subkey, MAXPATHLEN);
4438474SJose.Borrego@Sun.COM 	key->sk_predefined = B_FALSE;
4448474SJose.Borrego@Sun.COM 	list_insert_tail(&winreg_keylist.kl_list, key);
4458474SJose.Borrego@Sun.COM 	++winreg_keylist.kl_count;
4468474SJose.Borrego@Sun.COM 
4478474SJose.Borrego@Sun.COM 	bcopy(id, &param->result_handle, sizeof (winreg_handle_t));
448*11963SAfshin.Ardakani@Sun.COM 
449*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&winreg_mutex);
4508474SJose.Borrego@Sun.COM 	*action = WINREG_ACTION_NEW_KEY;
4518474SJose.Borrego@Sun.COM 	param->action = action;
4528474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
4538474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
454*11963SAfshin.Ardakani@Sun.COM 
455*11963SAfshin.Ardakani@Sun.COM no_memory:
456*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&winreg_mutex);
457*11963SAfshin.Ardakani@Sun.COM 	bzero(param, sizeof (struct winreg_CreateKey));
458*11963SAfshin.Ardakani@Sun.COM 	param->status = ERROR_NOT_ENOUGH_MEMORY;
459*11963SAfshin.Ardakani@Sun.COM 	return (NDR_DRC_OK);
4608474SJose.Borrego@Sun.COM }
4618474SJose.Borrego@Sun.COM 
4628474SJose.Borrego@Sun.COM /*
4638474SJose.Borrego@Sun.COM  * winreg_s_DeleteKey
4648474SJose.Borrego@Sun.COM  */
4658474SJose.Borrego@Sun.COM static int
4668474SJose.Borrego@Sun.COM winreg_s_DeleteKey(void *arg, ndr_xa_t *mxa)
4678474SJose.Borrego@Sun.COM {
4688474SJose.Borrego@Sun.COM 	struct winreg_DeleteKey *param = arg;
4698474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
4708474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
4718474SJose.Borrego@Sun.COM 	char *subkey;
4728474SJose.Borrego@Sun.COM 
4738474SJose.Borrego@Sun.COM 	subkey = (char *)param->subkey.str;
4748474SJose.Borrego@Sun.COM 
4758474SJose.Borrego@Sun.COM 	if (!ndr_is_admin(mxa) || (subkey == NULL)) {
4768474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
4778474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
4788474SJose.Borrego@Sun.COM 	}
4798474SJose.Borrego@Sun.COM 
480*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&winreg_mutex);
481*11963SAfshin.Ardakani@Sun.COM 
4828474SJose.Borrego@Sun.COM 	if ((ndr_hdlookup(mxa, id) == NULL) ||
4838474SJose.Borrego@Sun.COM 	    list_is_empty(&winreg_keylist.kl_list) ||
4848474SJose.Borrego@Sun.COM 	    winreg_key_has_subkey(subkey)) {
485*11963SAfshin.Ardakani@Sun.COM 		(void) mutex_unlock(&winreg_mutex);
4868474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
4878474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
4888474SJose.Borrego@Sun.COM 	}
4898474SJose.Borrego@Sun.COM 
4908474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
4918474SJose.Borrego@Sun.COM 	do {
4928474SJose.Borrego@Sun.COM 		if (strcasecmp(subkey, key->sk_name) == 0) {
4938474SJose.Borrego@Sun.COM 			if (key->sk_predefined == B_TRUE) {
4948474SJose.Borrego@Sun.COM 				/* Predefined keys cannot be deleted */
4958474SJose.Borrego@Sun.COM 				break;
4968474SJose.Borrego@Sun.COM 			}
4978474SJose.Borrego@Sun.COM 
4988474SJose.Borrego@Sun.COM 			list_remove(&winreg_keylist.kl_list, key);
4998474SJose.Borrego@Sun.COM 			--winreg_keylist.kl_count;
500*11963SAfshin.Ardakani@Sun.COM 			winreg_dealloc_id(mxa, &key->sk_handle);
501*11963SAfshin.Ardakani@Sun.COM 			free(key);
5028670SJose.Borrego@Sun.COM 
503*11963SAfshin.Ardakani@Sun.COM 			(void) mutex_unlock(&winreg_mutex);
5048474SJose.Borrego@Sun.COM 			param->status = ERROR_SUCCESS;
5058474SJose.Borrego@Sun.COM 			return (NDR_DRC_OK);
5068474SJose.Borrego@Sun.COM 		}
5078474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
5088474SJose.Borrego@Sun.COM 
509*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&winreg_mutex);
5108474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
5118474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
5128474SJose.Borrego@Sun.COM }
5138474SJose.Borrego@Sun.COM 
514*11963SAfshin.Ardakani@Sun.COM /*
515*11963SAfshin.Ardakani@Sun.COM  * Call with the winreg_mutex held.
516*11963SAfshin.Ardakani@Sun.COM  */
5178474SJose.Borrego@Sun.COM static boolean_t
5188474SJose.Borrego@Sun.COM winreg_key_has_subkey(const char *subkey)
5198474SJose.Borrego@Sun.COM {
5208474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
5218474SJose.Borrego@Sun.COM 	int keylen;
5228474SJose.Borrego@Sun.COM 
5238474SJose.Borrego@Sun.COM 	if (list_is_empty(&winreg_keylist.kl_list))
5248474SJose.Borrego@Sun.COM 		return (B_FALSE);
5258474SJose.Borrego@Sun.COM 
5268474SJose.Borrego@Sun.COM 	keylen = strlen(subkey);
5278474SJose.Borrego@Sun.COM 
5288474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
5298474SJose.Borrego@Sun.COM 	do {
5308474SJose.Borrego@Sun.COM 		if (strncasecmp(subkey, key->sk_name, keylen) == 0) {
5318474SJose.Borrego@Sun.COM 			/*
5328474SJose.Borrego@Sun.COM 			 * Potential match.  If sk_name is longer than
5338474SJose.Borrego@Sun.COM 			 * subkey, then sk_name is a subkey of our key.
5348474SJose.Borrego@Sun.COM 			 */
5358474SJose.Borrego@Sun.COM 			if (keylen < strlen(key->sk_name))
5368474SJose.Borrego@Sun.COM 				return (B_TRUE);
5378474SJose.Borrego@Sun.COM 		}
5388474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
5398474SJose.Borrego@Sun.COM 
5408474SJose.Borrego@Sun.COM 	return (B_FALSE);
5418474SJose.Borrego@Sun.COM }
5428474SJose.Borrego@Sun.COM 
543*11963SAfshin.Ardakani@Sun.COM /*
544*11963SAfshin.Ardakani@Sun.COM  * Call with the winreg_mutex held.
545*11963SAfshin.Ardakani@Sun.COM  */
5468474SJose.Borrego@Sun.COM static char *
5478670SJose.Borrego@Sun.COM winreg_enum_subkey(ndr_xa_t *mxa, const char *subkey, uint32_t index)
5488474SJose.Borrego@Sun.COM {
5498474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
5508670SJose.Borrego@Sun.COM 	char *entry;
5518670SJose.Borrego@Sun.COM 	char *p;
5528670SJose.Borrego@Sun.COM 	int subkeylen;
5538670SJose.Borrego@Sun.COM 	int count = 0;
5548474SJose.Borrego@Sun.COM 
5558474SJose.Borrego@Sun.COM 	if (subkey == NULL)
5568474SJose.Borrego@Sun.COM 		return (NULL);
5578474SJose.Borrego@Sun.COM 
5588474SJose.Borrego@Sun.COM 	if (list_is_empty(&winreg_keylist.kl_list))
5598474SJose.Borrego@Sun.COM 		return (NULL);
5608474SJose.Borrego@Sun.COM 
5618670SJose.Borrego@Sun.COM 	subkeylen = strlen(subkey);
5628670SJose.Borrego@Sun.COM 
5638670SJose.Borrego@Sun.COM 	for (key = list_head(&winreg_keylist.kl_list);
5648670SJose.Borrego@Sun.COM 	    key != NULL; key = list_next(&winreg_keylist.kl_list, key)) {
5658670SJose.Borrego@Sun.COM 		if (strncasecmp(subkey, key->sk_name, subkeylen) == 0) {
5668670SJose.Borrego@Sun.COM 			p = key->sk_name + subkeylen;
5678670SJose.Borrego@Sun.COM 
5688670SJose.Borrego@Sun.COM 			if ((*p != '\\') || (*p == '\0')) {
5698670SJose.Borrego@Sun.COM 				/*
5708670SJose.Borrego@Sun.COM 				 * Not the same subkey or an exact match.
5718670SJose.Borrego@Sun.COM 				 * We're looking for children of subkey.
5728670SJose.Borrego@Sun.COM 				 */
5738670SJose.Borrego@Sun.COM 				continue;
5748670SJose.Borrego@Sun.COM 			}
5758670SJose.Borrego@Sun.COM 
5768670SJose.Borrego@Sun.COM 			++p;
5778670SJose.Borrego@Sun.COM 
5788670SJose.Borrego@Sun.COM 			if (count < index) {
5798670SJose.Borrego@Sun.COM 				++count;
5808670SJose.Borrego@Sun.COM 				continue;
5818670SJose.Borrego@Sun.COM 			}
5828670SJose.Borrego@Sun.COM 
5838670SJose.Borrego@Sun.COM 			if ((entry = NDR_STRDUP(mxa, p)) == NULL)
5848670SJose.Borrego@Sun.COM 				return (NULL);
5858670SJose.Borrego@Sun.COM 
5868670SJose.Borrego@Sun.COM 			if ((p = strchr(entry, '\\')) != NULL)
5878670SJose.Borrego@Sun.COM 				*p = '\0';
5888670SJose.Borrego@Sun.COM 
5898670SJose.Borrego@Sun.COM 			return (entry);
5908474SJose.Borrego@Sun.COM 		}
5918670SJose.Borrego@Sun.COM 	}
5928474SJose.Borrego@Sun.COM 
5938474SJose.Borrego@Sun.COM 	return (NULL);
5948474SJose.Borrego@Sun.COM }
5958474SJose.Borrego@Sun.COM 
5968474SJose.Borrego@Sun.COM /*
5978474SJose.Borrego@Sun.COM  * winreg_s_DeleteValue
5988474SJose.Borrego@Sun.COM  */
5998474SJose.Borrego@Sun.COM /*ARGSUSED*/
6008474SJose.Borrego@Sun.COM static int
6018474SJose.Borrego@Sun.COM winreg_s_DeleteValue(void *arg, ndr_xa_t *mxa)
6028474SJose.Borrego@Sun.COM {
6038474SJose.Borrego@Sun.COM 	struct winreg_DeleteValue *param = arg;
6048474SJose.Borrego@Sun.COM 
6058474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
6068474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6078474SJose.Borrego@Sun.COM }
6088474SJose.Borrego@Sun.COM 
6098474SJose.Borrego@Sun.COM /*
6108474SJose.Borrego@Sun.COM  * winreg_s_EnumKey
6118474SJose.Borrego@Sun.COM  */
6128474SJose.Borrego@Sun.COM static int
6138474SJose.Borrego@Sun.COM winreg_s_EnumKey(void *arg, ndr_xa_t *mxa)
6148474SJose.Borrego@Sun.COM {
6158474SJose.Borrego@Sun.COM 	struct winreg_EnumKey *param = arg;
6168474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
6178670SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
6188670SJose.Borrego@Sun.COM 	char *subkey;
6198670SJose.Borrego@Sun.COM 	char *name = NULL;
6208474SJose.Borrego@Sun.COM 
621*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&winreg_mutex);
622*11963SAfshin.Ardakani@Sun.COM 
6238670SJose.Borrego@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) != NULL)
6248670SJose.Borrego@Sun.COM 		name = hd->nh_data;
6258474SJose.Borrego@Sun.COM 
6268670SJose.Borrego@Sun.COM 	if (hd == NULL || name == NULL) {
627*11963SAfshin.Ardakani@Sun.COM 		(void) mutex_unlock(&winreg_mutex);
6288474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumKey));
6298474SJose.Borrego@Sun.COM 		param->status = ERROR_NO_MORE_ITEMS;
6308474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6318474SJose.Borrego@Sun.COM 	}
6328474SJose.Borrego@Sun.COM 
6338670SJose.Borrego@Sun.COM 	subkey = winreg_enum_subkey(mxa, name, param->index);
6348670SJose.Borrego@Sun.COM 	if (subkey == NULL) {
635*11963SAfshin.Ardakani@Sun.COM 		(void) mutex_unlock(&winreg_mutex);
6368474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumKey));
6378670SJose.Borrego@Sun.COM 		param->status = ERROR_NO_MORE_ITEMS;
6388474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6398474SJose.Borrego@Sun.COM 	}
6408474SJose.Borrego@Sun.COM 
6418670SJose.Borrego@Sun.COM 	if (NDR_MSTRING(mxa, subkey, (ndr_mstring_t *)&param->name_out) == -1) {
642*11963SAfshin.Ardakani@Sun.COM 		(void) mutex_unlock(&winreg_mutex);
6438474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumKey));
6448474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
6458474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6468474SJose.Borrego@Sun.COM 	}
647*11963SAfshin.Ardakani@Sun.COM 
648*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&winreg_mutex);
649*11963SAfshin.Ardakani@Sun.COM 
6508670SJose.Borrego@Sun.COM 	/*
6518670SJose.Borrego@Sun.COM 	 * This request requires that the length includes the null.
6528670SJose.Borrego@Sun.COM 	 */
6538670SJose.Borrego@Sun.COM 	param->name_out.length = param->name_out.allosize;
6548474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
6558474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6568474SJose.Borrego@Sun.COM }
6578474SJose.Borrego@Sun.COM 
6588474SJose.Borrego@Sun.COM /*
6598474SJose.Borrego@Sun.COM  * winreg_s_EnumValue
6608474SJose.Borrego@Sun.COM  */
6618474SJose.Borrego@Sun.COM static int
6628474SJose.Borrego@Sun.COM winreg_s_EnumValue(void *arg, ndr_xa_t *mxa)
6638474SJose.Borrego@Sun.COM {
6648474SJose.Borrego@Sun.COM 	struct winreg_EnumValue *param = arg;
6658474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
6668474SJose.Borrego@Sun.COM 
6678474SJose.Borrego@Sun.COM 	if (ndr_hdlookup(mxa, id) == NULL) {
6688474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumValue));
6698474SJose.Borrego@Sun.COM 		param->status = ERROR_NO_MORE_ITEMS;
6708474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
6718474SJose.Borrego@Sun.COM 	}
6728474SJose.Borrego@Sun.COM 
6738474SJose.Borrego@Sun.COM 	bzero(param, sizeof (struct winreg_EnumValue));
6748474SJose.Borrego@Sun.COM 	param->status = ERROR_NO_MORE_ITEMS;
6758474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6768474SJose.Borrego@Sun.COM }
6778474SJose.Borrego@Sun.COM 
6788474SJose.Borrego@Sun.COM /*
6798474SJose.Borrego@Sun.COM  * winreg_s_FlushKey
6808474SJose.Borrego@Sun.COM  *
6818474SJose.Borrego@Sun.COM  * Flush the attributes associated with the specified open key to disk.
6828474SJose.Borrego@Sun.COM  */
6838474SJose.Borrego@Sun.COM static int
6848474SJose.Borrego@Sun.COM winreg_s_FlushKey(void *arg, ndr_xa_t *mxa)
6858474SJose.Borrego@Sun.COM {
6868474SJose.Borrego@Sun.COM 	struct winreg_FlushKey *param = arg;
6878474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
6888474SJose.Borrego@Sun.COM 
6898474SJose.Borrego@Sun.COM 	if (ndr_hdlookup(mxa, id) == NULL)
6908474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
6918474SJose.Borrego@Sun.COM 	else
6928474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
6938474SJose.Borrego@Sun.COM 
6948474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
6958474SJose.Borrego@Sun.COM }
6968474SJose.Borrego@Sun.COM 
6978474SJose.Borrego@Sun.COM /*
6988474SJose.Borrego@Sun.COM  * winreg_s_GetKeySec
6998474SJose.Borrego@Sun.COM  */
7008474SJose.Borrego@Sun.COM static int
7018474SJose.Borrego@Sun.COM winreg_s_GetKeySec(void *arg, ndr_xa_t *mxa)
7028474SJose.Borrego@Sun.COM {
70311633SJoyce.McIntosh@Sun.COM 	static struct winreg_secdesc	error_sd;
70411633SJoyce.McIntosh@Sun.COM 	struct winreg_GetKeySec		*param = arg;
70511633SJoyce.McIntosh@Sun.COM 	struct winreg_value		*sd_buf;
70611633SJoyce.McIntosh@Sun.COM 	smb_sd_t			sd;
70711633SJoyce.McIntosh@Sun.COM 	uint32_t			sd_len;
70811633SJoyce.McIntosh@Sun.COM 	uint32_t			status;
7098474SJose.Borrego@Sun.COM 
71011447Samw@Sun.COM 	bzero(&sd, sizeof (smb_sd_t));
71111447Samw@Sun.COM 
71211447Samw@Sun.COM 	if ((status = winreg_sd_format(&sd)) != ERROR_SUCCESS)
71311447Samw@Sun.COM 		goto winreg_getkeysec_error;
71411447Samw@Sun.COM 
71511447Samw@Sun.COM 	sd_len = smb_sd_len(&sd, SMB_ALL_SECINFO);
71611633SJoyce.McIntosh@Sun.COM 	sd_buf = NDR_MALLOC(mxa, sd_len + sizeof (struct winreg_value));
71711447Samw@Sun.COM 
71811447Samw@Sun.COM 	param->sd = NDR_MALLOC(mxa, sizeof (struct winreg_secdesc));
71911633SJoyce.McIntosh@Sun.COM 	if ((param->sd == NULL) || (sd_buf == NULL)) {
72011447Samw@Sun.COM 		status = ERROR_NOT_ENOUGH_MEMORY;
72111447Samw@Sun.COM 		goto winreg_getkeysec_error;
72211447Samw@Sun.COM 	}
72311447Samw@Sun.COM 
72411447Samw@Sun.COM 	param->sd->sd_len = sd_len;
72511447Samw@Sun.COM 	param->sd->sd_size = sd_len;
72611447Samw@Sun.COM 	param->sd->sd_buf = sd_buf;
72711447Samw@Sun.COM 
72811447Samw@Sun.COM 	sd_buf->vc_first_is = 0;
72911447Samw@Sun.COM 	sd_buf->vc_length_is = sd_len;
73011447Samw@Sun.COM 	param->status = srvsvc_sd_set_relative(&sd, sd_buf->value);
73111447Samw@Sun.COM 
73211447Samw@Sun.COM 	smb_sd_term(&sd);
73311447Samw@Sun.COM 	return (NDR_DRC_OK);
73411447Samw@Sun.COM 
73511447Samw@Sun.COM winreg_getkeysec_error:
73611447Samw@Sun.COM 	smb_sd_term(&sd);
7378474SJose.Borrego@Sun.COM 	bzero(param, sizeof (struct winreg_GetKeySec));
73811633SJoyce.McIntosh@Sun.COM 	param->sd = &error_sd;
73911447Samw@Sun.COM 	param->status = status;
7408474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
7418474SJose.Borrego@Sun.COM }
7428474SJose.Borrego@Sun.COM 
74311447Samw@Sun.COM static uint32_t
74411447Samw@Sun.COM winreg_sd_format(smb_sd_t *sd)
74511447Samw@Sun.COM {
74611447Samw@Sun.COM 	smb_fssd_t	fs_sd;
74711447Samw@Sun.COM 	acl_t		*acl;
74811447Samw@Sun.COM 	uint32_t	status = ERROR_SUCCESS;
74911447Samw@Sun.COM 
75011447Samw@Sun.COM 	if (acl_fromtext("owner@:rwxpdDaARWcCos::allow", &acl) != 0)
75111447Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
75211447Samw@Sun.COM 
75311447Samw@Sun.COM 	smb_fssd_init(&fs_sd, SMB_ALL_SECINFO, SMB_FSSD_FLAGS_DIR);
75411447Samw@Sun.COM 	fs_sd.sd_uid = 0;
75511447Samw@Sun.COM 	fs_sd.sd_gid = 0;
75611447Samw@Sun.COM 	fs_sd.sd_zdacl = acl;
75711447Samw@Sun.COM 	fs_sd.sd_zsacl = NULL;
75811447Samw@Sun.COM 
75911447Samw@Sun.COM 	if (smb_sd_fromfs(&fs_sd, sd) != NT_STATUS_SUCCESS)
76011447Samw@Sun.COM 		status = ERROR_ACCESS_DENIED;
76111447Samw@Sun.COM 	smb_fssd_term(&fs_sd);
76211447Samw@Sun.COM 	return (status);
76311447Samw@Sun.COM }
76411447Samw@Sun.COM 
7658474SJose.Borrego@Sun.COM /*
7668474SJose.Borrego@Sun.COM  * winreg_s_NotifyChange
7678474SJose.Borrego@Sun.COM  */
7688474SJose.Borrego@Sun.COM static int
7698474SJose.Borrego@Sun.COM winreg_s_NotifyChange(void *arg, ndr_xa_t *mxa)
7708474SJose.Borrego@Sun.COM {
7718474SJose.Borrego@Sun.COM 	struct winreg_NotifyChange *param = arg;
7728474SJose.Borrego@Sun.COM 
7738474SJose.Borrego@Sun.COM 	if (ndr_is_admin(mxa))
7748474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
7758474SJose.Borrego@Sun.COM 	else
7768474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
7778474SJose.Borrego@Sun.COM 
7788474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
7798474SJose.Borrego@Sun.COM }
7808474SJose.Borrego@Sun.COM 
7818474SJose.Borrego@Sun.COM /*
7828474SJose.Borrego@Sun.COM  * winreg_s_OpenKey
7838474SJose.Borrego@Sun.COM  *
7848474SJose.Borrego@Sun.COM  * This is a request to open a windows registry key.
7858474SJose.Borrego@Sun.COM  * If we recognize the key, we return a handle.
7868474SJose.Borrego@Sun.COM  *
7878474SJose.Borrego@Sun.COM  * Returns:
7888474SJose.Borrego@Sun.COM  *	ERROR_SUCCESS		Valid handle returned.
7898474SJose.Borrego@Sun.COM  *	ERROR_FILE_NOT_FOUND	No key or unable to allocate a handle.
7908474SJose.Borrego@Sun.COM  */
7918474SJose.Borrego@Sun.COM static int
7928474SJose.Borrego@Sun.COM winreg_s_OpenKey(void *arg, ndr_xa_t *mxa)
7938474SJose.Borrego@Sun.COM {
7948474SJose.Borrego@Sun.COM 	struct winreg_OpenKey *param = arg;
7959914Samw@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
7969914Samw@Sun.COM 	ndr_handle_t *hd;
7978474SJose.Borrego@Sun.COM 	char *subkey = (char *)param->name.str;
7988474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
799*11963SAfshin.Ardakani@Sun.COM 
800*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_lock(&winreg_mutex);
8018474SJose.Borrego@Sun.COM 
8029914Samw@Sun.COM 	if (subkey == NULL || *subkey == '\0') {
8039914Samw@Sun.COM 		if ((hd = ndr_hdlookup(mxa, id)) != NULL)
8049914Samw@Sun.COM 			subkey = hd->nh_data;
8059914Samw@Sun.COM 	}
8069914Samw@Sun.COM 
8079914Samw@Sun.COM 	id = NULL;
8089914Samw@Sun.COM 
8098670SJose.Borrego@Sun.COM 	if (subkey == NULL || list_is_empty(&winreg_keylist.kl_list)) {
810*11963SAfshin.Ardakani@Sun.COM 		(void) mutex_unlock(&winreg_mutex);
8118474SJose.Borrego@Sun.COM 		bzero(&param->result_handle, sizeof (winreg_handle_t));
8128474SJose.Borrego@Sun.COM 		param->status = ERROR_FILE_NOT_FOUND;
8138474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8148474SJose.Borrego@Sun.COM 	}
8158474SJose.Borrego@Sun.COM 
8168474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
8178474SJose.Borrego@Sun.COM 	do {
8188474SJose.Borrego@Sun.COM 		if (strcasecmp(subkey, key->sk_name) == 0) {
819*11963SAfshin.Ardakani@Sun.COM 			if (key->sk_predefined == B_TRUE)
820*11963SAfshin.Ardakani@Sun.COM 				id = winreg_alloc_id(mxa, subkey);
821*11963SAfshin.Ardakani@Sun.COM 			else
8228474SJose.Borrego@Sun.COM 				id = &key->sk_handle;
8238474SJose.Borrego@Sun.COM 
8248474SJose.Borrego@Sun.COM 			if (id == NULL)
8258474SJose.Borrego@Sun.COM 				break;
8268474SJose.Borrego@Sun.COM 
8278474SJose.Borrego@Sun.COM 			bcopy(id, &param->result_handle,
8288474SJose.Borrego@Sun.COM 			    sizeof (winreg_handle_t));
829*11963SAfshin.Ardakani@Sun.COM 
830*11963SAfshin.Ardakani@Sun.COM 			(void) mutex_unlock(&winreg_mutex);
8318474SJose.Borrego@Sun.COM 			param->status = ERROR_SUCCESS;
8328474SJose.Borrego@Sun.COM 			return (NDR_DRC_OK);
8338474SJose.Borrego@Sun.COM 		}
8348474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
8358474SJose.Borrego@Sun.COM 
836*11963SAfshin.Ardakani@Sun.COM 	(void) mutex_unlock(&winreg_mutex);
8378474SJose.Borrego@Sun.COM 	bzero(&param->result_handle, sizeof (winreg_handle_t));
8388474SJose.Borrego@Sun.COM 	param->status = ERROR_FILE_NOT_FOUND;
8398474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
8408474SJose.Borrego@Sun.COM }
8418474SJose.Borrego@Sun.COM 
8428474SJose.Borrego@Sun.COM /*
8438474SJose.Borrego@Sun.COM  * winreg_s_QueryKey
8448474SJose.Borrego@Sun.COM  */
8458474SJose.Borrego@Sun.COM /*ARGSUSED*/
8468474SJose.Borrego@Sun.COM static int
8478474SJose.Borrego@Sun.COM winreg_s_QueryKey(void *arg, ndr_xa_t *mxa)
8488474SJose.Borrego@Sun.COM {
8498474SJose.Borrego@Sun.COM 	struct winreg_QueryKey *param = arg;
8508474SJose.Borrego@Sun.COM 	int rc;
8518474SJose.Borrego@Sun.COM 	winreg_string_t	*name;
8528474SJose.Borrego@Sun.COM 
8538474SJose.Borrego@Sun.COM 	name = (winreg_string_t	*)&param->name;
8548474SJose.Borrego@Sun.COM 	bzero(param, sizeof (struct winreg_QueryKey));
855*11963SAfshin.Ardakani@Sun.COM 
8568474SJose.Borrego@Sun.COM 	if ((name = NDR_NEW(mxa, winreg_string_t)) != NULL)
8578474SJose.Borrego@Sun.COM 		rc = NDR_MSTRING(mxa, "", (ndr_mstring_t *)name);
8588474SJose.Borrego@Sun.COM 
8598474SJose.Borrego@Sun.COM 	if ((name == NULL) || (rc != 0)) {
8608474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_QueryKey));
8618474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
8628474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8638474SJose.Borrego@Sun.COM 	}
8648474SJose.Borrego@Sun.COM 
8658474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
8668474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
8678474SJose.Borrego@Sun.COM }
8688474SJose.Borrego@Sun.COM 
8698474SJose.Borrego@Sun.COM /*
8708474SJose.Borrego@Sun.COM  * winreg_s_QueryValue
8718474SJose.Borrego@Sun.COM  *
8728474SJose.Borrego@Sun.COM  * This is a request to get the value associated with a specified name.
8738474SJose.Borrego@Sun.COM  *
8748474SJose.Borrego@Sun.COM  * Returns:
8758474SJose.Borrego@Sun.COM  *	ERROR_SUCCESS		Value returned.
8768474SJose.Borrego@Sun.COM  *	ERROR_FILE_NOT_FOUND	PrimaryModule is not supported.
8778474SJose.Borrego@Sun.COM  *	ERROR_CANTREAD          No such name or memory problem.
8788474SJose.Borrego@Sun.COM  */
8798474SJose.Borrego@Sun.COM static int
8808474SJose.Borrego@Sun.COM winreg_s_QueryValue(void *arg, ndr_xa_t *mxa)
8818474SJose.Borrego@Sun.COM {
8828474SJose.Borrego@Sun.COM 	struct winreg_QueryValue *param = arg;
8838474SJose.Borrego@Sun.COM 	struct winreg_value *pv;
8848474SJose.Borrego@Sun.COM 	char *name;
8858474SJose.Borrego@Sun.COM 	char *value;
8868474SJose.Borrego@Sun.COM 	DWORD slen;
8878474SJose.Borrego@Sun.COM 	DWORD msize;
8888474SJose.Borrego@Sun.COM 
8898474SJose.Borrego@Sun.COM 	name = (char *)param->value_name.str;
8908474SJose.Borrego@Sun.COM 
8918474SJose.Borrego@Sun.COM 	if (strcasecmp(name, "PrimaryModule") == 0) {
8928474SJose.Borrego@Sun.COM 		param->status = ERROR_FILE_NOT_FOUND;
8938474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8948474SJose.Borrego@Sun.COM 	}
8958474SJose.Borrego@Sun.COM 
8968474SJose.Borrego@Sun.COM 	if ((value = winreg_lookup_value(name)) == NULL) {
8978474SJose.Borrego@Sun.COM 		param->status = ERROR_CANTREAD;
8988474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
8998474SJose.Borrego@Sun.COM 	}
9008474SJose.Borrego@Sun.COM 
90110966SJordan.Brown@Sun.COM 	slen = smb_wcequiv_strlen(value) + sizeof (smb_wchar_t);
9028474SJose.Borrego@Sun.COM 	msize = sizeof (struct winreg_value) + slen;
9038474SJose.Borrego@Sun.COM 
9048474SJose.Borrego@Sun.COM 	param->value = (struct winreg_value *)NDR_MALLOC(mxa, msize);
9058474SJose.Borrego@Sun.COM 	param->type = NDR_NEW(mxa, DWORD);
9068474SJose.Borrego@Sun.COM 	param->value_size = NDR_NEW(mxa, DWORD);
9078474SJose.Borrego@Sun.COM 	param->value_size_total = NDR_NEW(mxa, DWORD);
9088474SJose.Borrego@Sun.COM 
9098474SJose.Borrego@Sun.COM 	if (param->value == NULL || param->type == NULL ||
9108474SJose.Borrego@Sun.COM 	    param->value_size == NULL || param->value_size_total == NULL) {
9118474SJose.Borrego@Sun.COM 		param->status = ERROR_CANTREAD;
9128474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
9138474SJose.Borrego@Sun.COM 	}
9148474SJose.Borrego@Sun.COM 
9158474SJose.Borrego@Sun.COM 	bzero(param->value, msize);
9168474SJose.Borrego@Sun.COM 	pv = param->value;
9178474SJose.Borrego@Sun.COM 	pv->vc_first_is = 0;
9188474SJose.Borrego@Sun.COM 	pv->vc_length_is = slen;
9198474SJose.Borrego@Sun.COM 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
92010966SJordan.Brown@Sun.COM 	(void) ndr_mbstowcs(NULL, (smb_wchar_t *)pv->value, value, slen);
9218474SJose.Borrego@Sun.COM 
9228474SJose.Borrego@Sun.COM 	*param->type = 1;
9238474SJose.Borrego@Sun.COM 	*param->value_size = slen;
9248474SJose.Borrego@Sun.COM 	*param->value_size_total = slen;
9258474SJose.Borrego@Sun.COM 
9268474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
9278474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
9288474SJose.Borrego@Sun.COM }
9298474SJose.Borrego@Sun.COM 
9308474SJose.Borrego@Sun.COM /*
9318474SJose.Borrego@Sun.COM  * Lookup a name in the registry and return the associated value.
9328474SJose.Borrego@Sun.COM  * Our registry is a case-insensitive, name-value pair table.
9338474SJose.Borrego@Sun.COM  *
9348474SJose.Borrego@Sun.COM  * Windows ProductType: WinNT, ServerNT, LanmanNT.
9358474SJose.Borrego@Sun.COM  *	Windows NT4.0 workstation: WinNT
9368474SJose.Borrego@Sun.COM  *	Windows NT4.0 server:      ServerNT
9378474SJose.Borrego@Sun.COM  *
9388474SJose.Borrego@Sun.COM  * If LanmanNT is used here, Windows 2000 sends LsarQueryInfoPolicy
9398474SJose.Borrego@Sun.COM  * with info level 6, which we don't support.  If we use ServerNT
9408474SJose.Borrego@Sun.COM  * (as reported by NT4.0 Server) Windows 2000 send requests for
9418474SJose.Borrego@Sun.COM  * levels 3 and 5, which are support.
9428474SJose.Borrego@Sun.COM  *
9438474SJose.Borrego@Sun.COM  * On success, returns a pointer to the value.  Otherwise returns
9448474SJose.Borrego@Sun.COM  * a null pointer.
9458474SJose.Borrego@Sun.COM  */
9468474SJose.Borrego@Sun.COM static char *
9478474SJose.Borrego@Sun.COM winreg_lookup_value(const char *name)
9488474SJose.Borrego@Sun.COM {
9498474SJose.Borrego@Sun.COM 	static struct registry {
9508474SJose.Borrego@Sun.COM 		char *name;
9518474SJose.Borrego@Sun.COM 		char *value;
9528474SJose.Borrego@Sun.COM 	} registry[] = {
953*11963SAfshin.Ardakani@Sun.COM 		{ "SystemRoot",		"C:\\" },
954*11963SAfshin.Ardakani@Sun.COM 		{ "CurrentVersion",	winreg_sysver },
955*11963SAfshin.Ardakani@Sun.COM 		{ "ProductType",	"ServerNT" },
956*11963SAfshin.Ardakani@Sun.COM 		{ "Sources",		winreg_sysname }, /* product name */
957*11963SAfshin.Ardakani@Sun.COM 		{ "EventMessageFile",	"C:\\windows\\system32\\eventlog.dll" }
9588474SJose.Borrego@Sun.COM 	};
9598474SJose.Borrego@Sun.COM 
9608474SJose.Borrego@Sun.COM 	int i;
9618474SJose.Borrego@Sun.COM 
9628474SJose.Borrego@Sun.COM 	for (i = 0; i < sizeof (registry)/sizeof (registry[0]); ++i) {
963*11963SAfshin.Ardakani@Sun.COM 		if (strcasecmp(registry[i].name, name) == 0)
964*11963SAfshin.Ardakani@Sun.COM 			return (registry[i].value);
9658474SJose.Borrego@Sun.COM 	}
9668474SJose.Borrego@Sun.COM 
9678474SJose.Borrego@Sun.COM 	return (NULL);
9688474SJose.Borrego@Sun.COM }
9698474SJose.Borrego@Sun.COM 
9708474SJose.Borrego@Sun.COM /*
9718474SJose.Borrego@Sun.COM  * winreg_s_SetKeySec
9728474SJose.Borrego@Sun.COM  */
9738474SJose.Borrego@Sun.COM /*ARGSUSED*/
9748474SJose.Borrego@Sun.COM static int
9758474SJose.Borrego@Sun.COM winreg_s_SetKeySec(void *arg, ndr_xa_t *mxa)
9768474SJose.Borrego@Sun.COM {
9778474SJose.Borrego@Sun.COM 	struct winreg_SetKeySec *param = arg;
9788474SJose.Borrego@Sun.COM 
9798474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
9808474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
9818474SJose.Borrego@Sun.COM }
9828474SJose.Borrego@Sun.COM 
9838474SJose.Borrego@Sun.COM /*
9848474SJose.Borrego@Sun.COM  * winreg_s_CreateValue
9858474SJose.Borrego@Sun.COM  */
9868474SJose.Borrego@Sun.COM /*ARGSUSED*/
9878474SJose.Borrego@Sun.COM static int
9888474SJose.Borrego@Sun.COM winreg_s_CreateValue(void *arg, ndr_xa_t *mxa)
9898474SJose.Borrego@Sun.COM {
9908474SJose.Borrego@Sun.COM 	struct winreg_CreateValue *param = arg;
9918474SJose.Borrego@Sun.COM 
9928474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
9938474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
9948474SJose.Borrego@Sun.COM }
9958474SJose.Borrego@Sun.COM 
9968474SJose.Borrego@Sun.COM /*
9978474SJose.Borrego@Sun.COM  * winreg_s_Shutdown
9988474SJose.Borrego@Sun.COM  *
9998474SJose.Borrego@Sun.COM  * Attempt to shutdown or reboot the system: access denied.
10008474SJose.Borrego@Sun.COM  */
10018474SJose.Borrego@Sun.COM /*ARGSUSED*/
10028474SJose.Borrego@Sun.COM static int
10038474SJose.Borrego@Sun.COM winreg_s_Shutdown(void *arg, ndr_xa_t *mxa)
10048474SJose.Borrego@Sun.COM {
10058474SJose.Borrego@Sun.COM 	struct winreg_Shutdown *param = arg;
10068474SJose.Borrego@Sun.COM 
10078474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
10088474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
10098474SJose.Borrego@Sun.COM }
10108474SJose.Borrego@Sun.COM 
10118474SJose.Borrego@Sun.COM /*
10128474SJose.Borrego@Sun.COM  * winreg_s_AbortShutdown
10138474SJose.Borrego@Sun.COM  *
10148474SJose.Borrego@Sun.COM  * Abort a shutdown request.
10158474SJose.Borrego@Sun.COM  */
10168474SJose.Borrego@Sun.COM static int
10178474SJose.Borrego@Sun.COM winreg_s_AbortShutdown(void *arg, ndr_xa_t *mxa)
10188474SJose.Borrego@Sun.COM {
10198474SJose.Borrego@Sun.COM 	struct winreg_AbortShutdown *param = arg;
10208474SJose.Borrego@Sun.COM 
10218474SJose.Borrego@Sun.COM 	if (ndr_is_admin(mxa))
10228474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
10238474SJose.Borrego@Sun.COM 	else
10248474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
10258474SJose.Borrego@Sun.COM 
10268474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
10278474SJose.Borrego@Sun.COM }
10288474SJose.Borrego@Sun.COM 
10298474SJose.Borrego@Sun.COM /*
10308474SJose.Borrego@Sun.COM  * winreg_s_GetVersion
10318474SJose.Borrego@Sun.COM  *
10328474SJose.Borrego@Sun.COM  * Return the windows registry version.  The current version is 5.
10338474SJose.Borrego@Sun.COM  * This call is usually made prior to enumerating or querying registry
10348474SJose.Borrego@Sun.COM  * keys or values.
10358474SJose.Borrego@Sun.COM  */
10368474SJose.Borrego@Sun.COM /*ARGSUSED*/
10378474SJose.Borrego@Sun.COM static int
10388474SJose.Borrego@Sun.COM winreg_s_GetVersion(void *arg, ndr_xa_t *mxa)
10398474SJose.Borrego@Sun.COM {
10408474SJose.Borrego@Sun.COM 	struct winreg_GetVersion *param = arg;
10418474SJose.Borrego@Sun.COM 
10428474SJose.Borrego@Sun.COM 	param->version = 5;
10438474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
10448474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
10458474SJose.Borrego@Sun.COM }
1046