xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/winreg_svc.c (revision 8474:7803efd2fa77)
1*8474SJose.Borrego@Sun.COM /*
2*8474SJose.Borrego@Sun.COM  * CDDL HEADER START
3*8474SJose.Borrego@Sun.COM  *
4*8474SJose.Borrego@Sun.COM  * The contents of this file are subject to the terms of the
5*8474SJose.Borrego@Sun.COM  * Common Development and Distribution License (the "License").
6*8474SJose.Borrego@Sun.COM  * You may not use this file except in compliance with the License.
7*8474SJose.Borrego@Sun.COM  *
8*8474SJose.Borrego@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*8474SJose.Borrego@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*8474SJose.Borrego@Sun.COM  * See the License for the specific language governing permissions
11*8474SJose.Borrego@Sun.COM  * and limitations under the License.
12*8474SJose.Borrego@Sun.COM  *
13*8474SJose.Borrego@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*8474SJose.Borrego@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*8474SJose.Borrego@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*8474SJose.Borrego@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*8474SJose.Borrego@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*8474SJose.Borrego@Sun.COM  *
19*8474SJose.Borrego@Sun.COM  * CDDL HEADER END
20*8474SJose.Borrego@Sun.COM  */
21*8474SJose.Borrego@Sun.COM /*
22*8474SJose.Borrego@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*8474SJose.Borrego@Sun.COM  * Use is subject to license terms.
24*8474SJose.Borrego@Sun.COM  */
25*8474SJose.Borrego@Sun.COM 
26*8474SJose.Borrego@Sun.COM /*
27*8474SJose.Borrego@Sun.COM  * Windows Registry RPC (WINREG) server-side interface.
28*8474SJose.Borrego@Sun.COM  *
29*8474SJose.Borrego@Sun.COM  * The WINREG RPC interface returns Win32 error codes.
30*8474SJose.Borrego@Sun.COM  *
31*8474SJose.Borrego@Sun.COM  * HKLM		Hive Key Local Machine
32*8474SJose.Borrego@Sun.COM  * HKU		Hive Key Users
33*8474SJose.Borrego@Sun.COM  */
34*8474SJose.Borrego@Sun.COM 
35*8474SJose.Borrego@Sun.COM #include <sys/utsname.h>
36*8474SJose.Borrego@Sun.COM #include <strings.h>
37*8474SJose.Borrego@Sun.COM 
38*8474SJose.Borrego@Sun.COM #include <smbsrv/libsmb.h>
39*8474SJose.Borrego@Sun.COM #include <smbsrv/ntstatus.h>
40*8474SJose.Borrego@Sun.COM #include <smbsrv/nterror.h>
41*8474SJose.Borrego@Sun.COM #include <smbsrv/nmpipes.h>
42*8474SJose.Borrego@Sun.COM #include <smbsrv/libmlsvc.h>
43*8474SJose.Borrego@Sun.COM #include <smbsrv/ndl/winreg.ndl>
44*8474SJose.Borrego@Sun.COM 
45*8474SJose.Borrego@Sun.COM #define	WINREG_LOGR_SYSTEMKEY	\
46*8474SJose.Borrego@Sun.COM 	"System\\CurrentControlSet\\Services\\Eventlog\\System"
47*8474SJose.Borrego@Sun.COM 
48*8474SJose.Borrego@Sun.COM /*
49*8474SJose.Borrego@Sun.COM  * Local handle management keys.
50*8474SJose.Borrego@Sun.COM  */
51*8474SJose.Borrego@Sun.COM static int winreg_hk;
52*8474SJose.Borrego@Sun.COM static int winreg_hklm;
53*8474SJose.Borrego@Sun.COM static int winreg_hkuser;
54*8474SJose.Borrego@Sun.COM static int winreg_hkkey;
55*8474SJose.Borrego@Sun.COM 
56*8474SJose.Borrego@Sun.COM /*
57*8474SJose.Borrego@Sun.COM  * List of supported registry keys (case-insensitive).
58*8474SJose.Borrego@Sun.COM  */
59*8474SJose.Borrego@Sun.COM static char *winreg_keys[] = {
60*8474SJose.Borrego@Sun.COM 	"System\\CurrentControlSet\\Services\\Eventlog",
61*8474SJose.Borrego@Sun.COM 	"System\\CurrentControlSet\\Services\\Eventlog\\System",
62*8474SJose.Borrego@Sun.COM 	"System\\CurrentControlSet\\Control\\ProductOptions",
63*8474SJose.Borrego@Sun.COM 	"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
64*8474SJose.Borrego@Sun.COM };
65*8474SJose.Borrego@Sun.COM 
66*8474SJose.Borrego@Sun.COM typedef struct winreg_subkey {
67*8474SJose.Borrego@Sun.COM 	list_node_t sk_lnd;
68*8474SJose.Borrego@Sun.COM 	ndr_hdid_t sk_handle;
69*8474SJose.Borrego@Sun.COM 	char sk_name[MAXPATHLEN];
70*8474SJose.Borrego@Sun.COM 	boolean_t sk_predefined;
71*8474SJose.Borrego@Sun.COM } winreg_subkey_t;
72*8474SJose.Borrego@Sun.COM 
73*8474SJose.Borrego@Sun.COM typedef struct winreg_keylist {
74*8474SJose.Borrego@Sun.COM 	list_t kl_list;
75*8474SJose.Borrego@Sun.COM 	int kl_count;
76*8474SJose.Borrego@Sun.COM } winreg_keylist_t;
77*8474SJose.Borrego@Sun.COM 
78*8474SJose.Borrego@Sun.COM static winreg_keylist_t winreg_keylist;
79*8474SJose.Borrego@Sun.COM 
80*8474SJose.Borrego@Sun.COM static boolean_t winreg_key_has_subkey(const char *);
81*8474SJose.Borrego@Sun.COM static char *winreg_lookup_value(const char *);
82*8474SJose.Borrego@Sun.COM static char *winreg_lookup_eventlog_registry(char *, char *);
83*8474SJose.Borrego@Sun.COM 
84*8474SJose.Borrego@Sun.COM static int winreg_s_OpenHK(void *, ndr_xa_t *);
85*8474SJose.Borrego@Sun.COM static int winreg_s_OpenHKLM(void *, ndr_xa_t *);
86*8474SJose.Borrego@Sun.COM static int winreg_s_OpenHKUsers(void *, ndr_xa_t *);
87*8474SJose.Borrego@Sun.COM static int winreg_s_Close(void *, ndr_xa_t *);
88*8474SJose.Borrego@Sun.COM static int winreg_s_CreateKey(void *, ndr_xa_t *);
89*8474SJose.Borrego@Sun.COM static int winreg_s_DeleteKey(void *, ndr_xa_t *);
90*8474SJose.Borrego@Sun.COM static int winreg_s_DeleteValue(void *, ndr_xa_t *);
91*8474SJose.Borrego@Sun.COM static int winreg_s_EnumKey(void *, ndr_xa_t *);
92*8474SJose.Borrego@Sun.COM static int winreg_s_EnumValue(void *, ndr_xa_t *);
93*8474SJose.Borrego@Sun.COM static int winreg_s_FlushKey(void *, ndr_xa_t *);
94*8474SJose.Borrego@Sun.COM static int winreg_s_GetKeySec(void *, ndr_xa_t *);
95*8474SJose.Borrego@Sun.COM static int winreg_s_NotifyChange(void *, ndr_xa_t *);
96*8474SJose.Borrego@Sun.COM static int winreg_s_OpenKey(void *, ndr_xa_t *);
97*8474SJose.Borrego@Sun.COM static int winreg_s_QueryKey(void *, ndr_xa_t *);
98*8474SJose.Borrego@Sun.COM static int winreg_s_QueryValue(void *, ndr_xa_t *);
99*8474SJose.Borrego@Sun.COM static int winreg_s_SetKeySec(void *, ndr_xa_t *);
100*8474SJose.Borrego@Sun.COM static int winreg_s_CreateValue(void *, ndr_xa_t *);
101*8474SJose.Borrego@Sun.COM static int winreg_s_Shutdown(void *, ndr_xa_t *);
102*8474SJose.Borrego@Sun.COM static int winreg_s_AbortShutdown(void *, ndr_xa_t *);
103*8474SJose.Borrego@Sun.COM static int winreg_s_GetVersion(void *, ndr_xa_t *);
104*8474SJose.Borrego@Sun.COM 
105*8474SJose.Borrego@Sun.COM static ndr_stub_table_t winreg_stub_table[] = {
106*8474SJose.Borrego@Sun.COM 	{ winreg_s_OpenHK,	WINREG_OPNUM_OpenHKCR },
107*8474SJose.Borrego@Sun.COM 	{ winreg_s_OpenHK,	WINREG_OPNUM_OpenHKCU },
108*8474SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKLM,	WINREG_OPNUM_OpenHKLM },
109*8474SJose.Borrego@Sun.COM 	{ winreg_s_OpenHK,	WINREG_OPNUM_OpenHKPD },
110*8474SJose.Borrego@Sun.COM 	{ winreg_s_OpenHKUsers,	WINREG_OPNUM_OpenHKUsers },
111*8474SJose.Borrego@Sun.COM 	{ winreg_s_Close,	WINREG_OPNUM_Close },
112*8474SJose.Borrego@Sun.COM 	{ winreg_s_CreateKey,	WINREG_OPNUM_CreateKey },
113*8474SJose.Borrego@Sun.COM 	{ winreg_s_DeleteKey,	WINREG_OPNUM_DeleteKey },
114*8474SJose.Borrego@Sun.COM 	{ winreg_s_DeleteValue,	WINREG_OPNUM_DeleteValue },
115*8474SJose.Borrego@Sun.COM 	{ winreg_s_EnumKey,	WINREG_OPNUM_EnumKey },
116*8474SJose.Borrego@Sun.COM 	{ winreg_s_EnumValue,	WINREG_OPNUM_EnumValue },
117*8474SJose.Borrego@Sun.COM 	{ winreg_s_FlushKey,	WINREG_OPNUM_FlushKey },
118*8474SJose.Borrego@Sun.COM 	{ winreg_s_GetKeySec,	WINREG_OPNUM_GetKeySec },
119*8474SJose.Borrego@Sun.COM 	{ winreg_s_NotifyChange,	WINREG_OPNUM_NotifyChange },
120*8474SJose.Borrego@Sun.COM 	{ winreg_s_OpenKey,	WINREG_OPNUM_OpenKey },
121*8474SJose.Borrego@Sun.COM 	{ winreg_s_QueryKey,	WINREG_OPNUM_QueryKey },
122*8474SJose.Borrego@Sun.COM 	{ winreg_s_QueryValue,	WINREG_OPNUM_QueryValue },
123*8474SJose.Borrego@Sun.COM 	{ winreg_s_SetKeySec,	WINREG_OPNUM_SetKeySec },
124*8474SJose.Borrego@Sun.COM 	{ winreg_s_CreateValue,	WINREG_OPNUM_CreateValue },
125*8474SJose.Borrego@Sun.COM 	{ winreg_s_Shutdown,	WINREG_OPNUM_Shutdown },
126*8474SJose.Borrego@Sun.COM 	{ winreg_s_AbortShutdown,	WINREG_OPNUM_AbortShutdown },
127*8474SJose.Borrego@Sun.COM 	{ winreg_s_GetVersion,	WINREG_OPNUM_GetVersion },
128*8474SJose.Borrego@Sun.COM 	{ winreg_s_OpenHK,	WINREG_OPNUM_OpenHKCC },
129*8474SJose.Borrego@Sun.COM 	{ winreg_s_OpenHK,	WINREG_OPNUM_OpenHKDD },
130*8474SJose.Borrego@Sun.COM 	{ winreg_s_OpenHK,	WINREG_OPNUM_OpenHKPT },
131*8474SJose.Borrego@Sun.COM 	{ winreg_s_OpenHK,	WINREG_OPNUM_OpenHKPN },
132*8474SJose.Borrego@Sun.COM 	{0}
133*8474SJose.Borrego@Sun.COM };
134*8474SJose.Borrego@Sun.COM 
135*8474SJose.Borrego@Sun.COM static ndr_service_t winreg_service = {
136*8474SJose.Borrego@Sun.COM 	"Winreg",			/* name */
137*8474SJose.Borrego@Sun.COM 	"Windows Registry",		/* desc */
138*8474SJose.Borrego@Sun.COM 	"\\winreg",			/* endpoint */
139*8474SJose.Borrego@Sun.COM 	PIPE_WINREG,			/* sec_addr_port */
140*8474SJose.Borrego@Sun.COM 	"338cd001-2244-31f1-aaaa-900038001003", 1,	/* abstract */
141*8474SJose.Borrego@Sun.COM 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
142*8474SJose.Borrego@Sun.COM 	0,				/* no bind_instance_size */
143*8474SJose.Borrego@Sun.COM 	0,				/* no bind_req() */
144*8474SJose.Borrego@Sun.COM 	0,				/* no unbind_and_close() */
145*8474SJose.Borrego@Sun.COM 	0,				/* use generic_call_stub() */
146*8474SJose.Borrego@Sun.COM 	&TYPEINFO(winreg_interface),	/* interface ti */
147*8474SJose.Borrego@Sun.COM 	winreg_stub_table		/* stub_table */
148*8474SJose.Borrego@Sun.COM };
149*8474SJose.Borrego@Sun.COM 
150*8474SJose.Borrego@Sun.COM static char winreg_sysname[SYS_NMLN];
151*8474SJose.Borrego@Sun.COM 
152*8474SJose.Borrego@Sun.COM /*
153*8474SJose.Borrego@Sun.COM  * winreg_initialize
154*8474SJose.Borrego@Sun.COM  *
155*8474SJose.Borrego@Sun.COM  * Initialize and register the WINREG RPC interface with the RPC runtime
156*8474SJose.Borrego@Sun.COM  * library. It must be called in order to use either the client side
157*8474SJose.Borrego@Sun.COM  * or the server side functions.
158*8474SJose.Borrego@Sun.COM  */
159*8474SJose.Borrego@Sun.COM void
160*8474SJose.Borrego@Sun.COM winreg_initialize(void)
161*8474SJose.Borrego@Sun.COM {
162*8474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
163*8474SJose.Borrego@Sun.COM 	struct utsname name;
164*8474SJose.Borrego@Sun.COM 	char *sysname;
165*8474SJose.Borrego@Sun.COM 	int i;
166*8474SJose.Borrego@Sun.COM 
167*8474SJose.Borrego@Sun.COM 	list_create(&winreg_keylist.kl_list, sizeof (winreg_subkey_t),
168*8474SJose.Borrego@Sun.COM 	    offsetof(winreg_subkey_t, sk_lnd));
169*8474SJose.Borrego@Sun.COM 	winreg_keylist.kl_count = 0;
170*8474SJose.Borrego@Sun.COM 
171*8474SJose.Borrego@Sun.COM 	for (i = 0; i < sizeof (winreg_keys)/sizeof (winreg_keys[0]); ++i) {
172*8474SJose.Borrego@Sun.COM 		if ((key = malloc(sizeof (winreg_subkey_t))) != NULL) {
173*8474SJose.Borrego@Sun.COM 			bzero(key, sizeof (winreg_subkey_t));
174*8474SJose.Borrego@Sun.COM 			(void) strlcpy(key->sk_name, winreg_keys[i],
175*8474SJose.Borrego@Sun.COM 			    MAXPATHLEN);
176*8474SJose.Borrego@Sun.COM 			key->sk_predefined = B_TRUE;
177*8474SJose.Borrego@Sun.COM 			list_insert_tail(&winreg_keylist.kl_list, key);
178*8474SJose.Borrego@Sun.COM 			++winreg_keylist.kl_count;
179*8474SJose.Borrego@Sun.COM 		}
180*8474SJose.Borrego@Sun.COM 	}
181*8474SJose.Borrego@Sun.COM 
182*8474SJose.Borrego@Sun.COM 	if (uname(&name) < 0)
183*8474SJose.Borrego@Sun.COM 		sysname = "Solaris";
184*8474SJose.Borrego@Sun.COM 	else
185*8474SJose.Borrego@Sun.COM 		sysname = name.sysname;
186*8474SJose.Borrego@Sun.COM 
187*8474SJose.Borrego@Sun.COM 	(void) strlcpy(winreg_sysname, sysname, SYS_NMLN);
188*8474SJose.Borrego@Sun.COM 	(void) ndr_svc_register(&winreg_service);
189*8474SJose.Borrego@Sun.COM }
190*8474SJose.Borrego@Sun.COM 
191*8474SJose.Borrego@Sun.COM /*
192*8474SJose.Borrego@Sun.COM  * winreg_s_OpenHK
193*8474SJose.Borrego@Sun.COM  *
194*8474SJose.Borrego@Sun.COM  * Stub.
195*8474SJose.Borrego@Sun.COM  */
196*8474SJose.Borrego@Sun.COM static int
197*8474SJose.Borrego@Sun.COM winreg_s_OpenHK(void *arg, ndr_xa_t *mxa)
198*8474SJose.Borrego@Sun.COM {
199*8474SJose.Borrego@Sun.COM 	struct winreg_OpenHKCR *param = arg;
200*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id;
201*8474SJose.Borrego@Sun.COM 
202*8474SJose.Borrego@Sun.COM 	if ((id = ndr_hdalloc(mxa, &winreg_hk)) == NULL) {
203*8474SJose.Borrego@Sun.COM 		bzero(&param->handle, sizeof (winreg_handle_t));
204*8474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
205*8474SJose.Borrego@Sun.COM 	} else {
206*8474SJose.Borrego@Sun.COM 		bcopy(id, &param->handle, sizeof (winreg_handle_t));
207*8474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
208*8474SJose.Borrego@Sun.COM 	}
209*8474SJose.Borrego@Sun.COM 
210*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
211*8474SJose.Borrego@Sun.COM }
212*8474SJose.Borrego@Sun.COM 
213*8474SJose.Borrego@Sun.COM /*
214*8474SJose.Borrego@Sun.COM  * winreg_s_OpenHKLM
215*8474SJose.Borrego@Sun.COM  *
216*8474SJose.Borrego@Sun.COM  * This is a request to open the HKLM and get a handle.
217*8474SJose.Borrego@Sun.COM  * The client should treat the handle as an opaque object.
218*8474SJose.Borrego@Sun.COM  *
219*8474SJose.Borrego@Sun.COM  * Status:
220*8474SJose.Borrego@Sun.COM  *	ERROR_SUCCESS		Valid handle returned.
221*8474SJose.Borrego@Sun.COM  *	ERROR_ACCESS_DENIED	Unable to allocate a handle.
222*8474SJose.Borrego@Sun.COM  */
223*8474SJose.Borrego@Sun.COM static int
224*8474SJose.Borrego@Sun.COM winreg_s_OpenHKLM(void *arg, ndr_xa_t *mxa)
225*8474SJose.Borrego@Sun.COM {
226*8474SJose.Borrego@Sun.COM 	struct winreg_OpenHKLM *param = arg;
227*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id;
228*8474SJose.Borrego@Sun.COM 
229*8474SJose.Borrego@Sun.COM 	if ((id = ndr_hdalloc(mxa, &winreg_hklm)) == NULL) {
230*8474SJose.Borrego@Sun.COM 		bzero(&param->handle, sizeof (winreg_handle_t));
231*8474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
232*8474SJose.Borrego@Sun.COM 	} else {
233*8474SJose.Borrego@Sun.COM 		bcopy(id, &param->handle, sizeof (winreg_handle_t));
234*8474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
235*8474SJose.Borrego@Sun.COM 	}
236*8474SJose.Borrego@Sun.COM 
237*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
238*8474SJose.Borrego@Sun.COM }
239*8474SJose.Borrego@Sun.COM 
240*8474SJose.Borrego@Sun.COM /*
241*8474SJose.Borrego@Sun.COM  * winreg_s_OpenHKUsers
242*8474SJose.Borrego@Sun.COM  *
243*8474SJose.Borrego@Sun.COM  * This is a request to get a HKUsers handle. I'm not sure we are
244*8474SJose.Borrego@Sun.COM  * ready to fully support this interface yet, mostly due to the need
245*8474SJose.Borrego@Sun.COM  * to support subsequent requests, but we may support enough now. It
246*8474SJose.Borrego@Sun.COM  * seems okay with regedt32.
247*8474SJose.Borrego@Sun.COM  */
248*8474SJose.Borrego@Sun.COM static int
249*8474SJose.Borrego@Sun.COM winreg_s_OpenHKUsers(void *arg, ndr_xa_t *mxa)
250*8474SJose.Borrego@Sun.COM {
251*8474SJose.Borrego@Sun.COM 	struct winreg_OpenHKUsers *param = arg;
252*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id;
253*8474SJose.Borrego@Sun.COM 
254*8474SJose.Borrego@Sun.COM 	if ((id = ndr_hdalloc(mxa, &winreg_hkuser)) == NULL) {
255*8474SJose.Borrego@Sun.COM 		bzero(&param->handle, sizeof (winreg_handle_t));
256*8474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
257*8474SJose.Borrego@Sun.COM 	} else {
258*8474SJose.Borrego@Sun.COM 		bcopy(id, &param->handle, sizeof (winreg_handle_t));
259*8474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
260*8474SJose.Borrego@Sun.COM 	}
261*8474SJose.Borrego@Sun.COM 
262*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
263*8474SJose.Borrego@Sun.COM }
264*8474SJose.Borrego@Sun.COM 
265*8474SJose.Borrego@Sun.COM /*
266*8474SJose.Borrego@Sun.COM  * winreg_s_Close
267*8474SJose.Borrego@Sun.COM  *
268*8474SJose.Borrego@Sun.COM  * This is a request to close the WINREG interface specified by the
269*8474SJose.Borrego@Sun.COM  * handle. We don't track handles (yet), so just zero out the handle
270*8474SJose.Borrego@Sun.COM  * and return NDR_DRC_OK. Setting the handle to zero appears to be
271*8474SJose.Borrego@Sun.COM  * standard behaviour.
272*8474SJose.Borrego@Sun.COM  */
273*8474SJose.Borrego@Sun.COM static int
274*8474SJose.Borrego@Sun.COM winreg_s_Close(void *arg, ndr_xa_t *mxa)
275*8474SJose.Borrego@Sun.COM {
276*8474SJose.Borrego@Sun.COM 	struct winreg_Close *param = arg;
277*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
278*8474SJose.Borrego@Sun.COM 
279*8474SJose.Borrego@Sun.COM 	ndr_hdfree(mxa, id);
280*8474SJose.Borrego@Sun.COM 
281*8474SJose.Borrego@Sun.COM 	bzero(&param->result_handle, sizeof (winreg_handle_t));
282*8474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
283*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
284*8474SJose.Borrego@Sun.COM }
285*8474SJose.Borrego@Sun.COM 
286*8474SJose.Borrego@Sun.COM /*
287*8474SJose.Borrego@Sun.COM  * winreg_s_CreateKey
288*8474SJose.Borrego@Sun.COM  */
289*8474SJose.Borrego@Sun.COM static int
290*8474SJose.Borrego@Sun.COM winreg_s_CreateKey(void *arg, ndr_xa_t *mxa)
291*8474SJose.Borrego@Sun.COM {
292*8474SJose.Borrego@Sun.COM 	struct winreg_CreateKey *param = arg;
293*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
294*8474SJose.Borrego@Sun.COM 	ndr_handle_t *hd;
295*8474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
296*8474SJose.Borrego@Sun.COM 	char *subkey;
297*8474SJose.Borrego@Sun.COM 	DWORD *action;
298*8474SJose.Borrego@Sun.COM 
299*8474SJose.Borrego@Sun.COM 	subkey = (char *)param->subkey.str;
300*8474SJose.Borrego@Sun.COM 
301*8474SJose.Borrego@Sun.COM 	if (!ndr_is_admin(mxa) || (subkey == NULL)) {
302*8474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
303*8474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
304*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
305*8474SJose.Borrego@Sun.COM 	}
306*8474SJose.Borrego@Sun.COM 
307*8474SJose.Borrego@Sun.COM 	hd = ndr_hdlookup(mxa, id);
308*8474SJose.Borrego@Sun.COM 	if (hd == NULL) {
309*8474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
310*8474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
311*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
312*8474SJose.Borrego@Sun.COM 	}
313*8474SJose.Borrego@Sun.COM 
314*8474SJose.Borrego@Sun.COM 	if ((action = NDR_NEW(mxa, DWORD)) == NULL) {
315*8474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
316*8474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
317*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
318*8474SJose.Borrego@Sun.COM 	}
319*8474SJose.Borrego@Sun.COM 
320*8474SJose.Borrego@Sun.COM 	if (list_is_empty(&winreg_keylist.kl_list))
321*8474SJose.Borrego@Sun.COM 		goto new_key;
322*8474SJose.Borrego@Sun.COM 
323*8474SJose.Borrego@Sun.COM 	/*
324*8474SJose.Borrego@Sun.COM 	 * Check for an existing key.
325*8474SJose.Borrego@Sun.COM 	 */
326*8474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
327*8474SJose.Borrego@Sun.COM 	do {
328*8474SJose.Borrego@Sun.COM 		if (strcasecmp(subkey, key->sk_name) == 0) {
329*8474SJose.Borrego@Sun.COM 			bcopy(&key->sk_handle, &param->result_handle,
330*8474SJose.Borrego@Sun.COM 			    sizeof (winreg_handle_t));
331*8474SJose.Borrego@Sun.COM 			*action = WINREG_ACTION_EXISTING_KEY;
332*8474SJose.Borrego@Sun.COM 			param->action = action;
333*8474SJose.Borrego@Sun.COM 			param->status = ERROR_SUCCESS;
334*8474SJose.Borrego@Sun.COM 			return (NDR_DRC_OK);
335*8474SJose.Borrego@Sun.COM 		}
336*8474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
337*8474SJose.Borrego@Sun.COM 
338*8474SJose.Borrego@Sun.COM new_key:
339*8474SJose.Borrego@Sun.COM 	/*
340*8474SJose.Borrego@Sun.COM 	 * Create a new key.
341*8474SJose.Borrego@Sun.COM 	 */
342*8474SJose.Borrego@Sun.COM 	id = ndr_hdalloc(mxa, &winreg_hkkey);
343*8474SJose.Borrego@Sun.COM 	key = malloc(sizeof (winreg_subkey_t));
344*8474SJose.Borrego@Sun.COM 
345*8474SJose.Borrego@Sun.COM 	if ((id == NULL) || (key == NULL)) {
346*8474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_CreateKey));
347*8474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
348*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
349*8474SJose.Borrego@Sun.COM 	}
350*8474SJose.Borrego@Sun.COM 
351*8474SJose.Borrego@Sun.COM 	bcopy(id, &key->sk_handle, sizeof (ndr_hdid_t));
352*8474SJose.Borrego@Sun.COM 	(void) strlcpy(key->sk_name, subkey, MAXPATHLEN);
353*8474SJose.Borrego@Sun.COM 	key->sk_predefined = B_FALSE;
354*8474SJose.Borrego@Sun.COM 	list_insert_tail(&winreg_keylist.kl_list, key);
355*8474SJose.Borrego@Sun.COM 	++winreg_keylist.kl_count;
356*8474SJose.Borrego@Sun.COM 
357*8474SJose.Borrego@Sun.COM 	bcopy(id, &param->result_handle, sizeof (winreg_handle_t));
358*8474SJose.Borrego@Sun.COM 	*action = WINREG_ACTION_NEW_KEY;
359*8474SJose.Borrego@Sun.COM 	param->action = action;
360*8474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
361*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
362*8474SJose.Borrego@Sun.COM }
363*8474SJose.Borrego@Sun.COM 
364*8474SJose.Borrego@Sun.COM /*
365*8474SJose.Borrego@Sun.COM  * winreg_s_DeleteKey
366*8474SJose.Borrego@Sun.COM  */
367*8474SJose.Borrego@Sun.COM static int
368*8474SJose.Borrego@Sun.COM winreg_s_DeleteKey(void *arg, ndr_xa_t *mxa)
369*8474SJose.Borrego@Sun.COM {
370*8474SJose.Borrego@Sun.COM 	struct winreg_DeleteKey *param = arg;
371*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
372*8474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
373*8474SJose.Borrego@Sun.COM 	char *subkey;
374*8474SJose.Borrego@Sun.COM 
375*8474SJose.Borrego@Sun.COM 	subkey = (char *)param->subkey.str;
376*8474SJose.Borrego@Sun.COM 
377*8474SJose.Borrego@Sun.COM 	if (!ndr_is_admin(mxa) || (subkey == NULL)) {
378*8474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
379*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
380*8474SJose.Borrego@Sun.COM 	}
381*8474SJose.Borrego@Sun.COM 
382*8474SJose.Borrego@Sun.COM 	if ((ndr_hdlookup(mxa, id) == NULL) ||
383*8474SJose.Borrego@Sun.COM 	    list_is_empty(&winreg_keylist.kl_list) ||
384*8474SJose.Borrego@Sun.COM 	    winreg_key_has_subkey(subkey)) {
385*8474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
386*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
387*8474SJose.Borrego@Sun.COM 	}
388*8474SJose.Borrego@Sun.COM 
389*8474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
390*8474SJose.Borrego@Sun.COM 	do {
391*8474SJose.Borrego@Sun.COM 		if (strcasecmp(subkey, key->sk_name) == 0) {
392*8474SJose.Borrego@Sun.COM 			if (key->sk_predefined == B_TRUE) {
393*8474SJose.Borrego@Sun.COM 				/* Predefined keys cannot be deleted */
394*8474SJose.Borrego@Sun.COM 				break;
395*8474SJose.Borrego@Sun.COM 			}
396*8474SJose.Borrego@Sun.COM 
397*8474SJose.Borrego@Sun.COM 			list_remove(&winreg_keylist.kl_list, key);
398*8474SJose.Borrego@Sun.COM 			--winreg_keylist.kl_count;
399*8474SJose.Borrego@Sun.COM 			ndr_hdfree(mxa, &key->sk_handle);
400*8474SJose.Borrego@Sun.COM 			free(key);
401*8474SJose.Borrego@Sun.COM 			param->status = ERROR_SUCCESS;
402*8474SJose.Borrego@Sun.COM 			return (NDR_DRC_OK);
403*8474SJose.Borrego@Sun.COM 		}
404*8474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
405*8474SJose.Borrego@Sun.COM 
406*8474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
407*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
408*8474SJose.Borrego@Sun.COM }
409*8474SJose.Borrego@Sun.COM 
410*8474SJose.Borrego@Sun.COM static boolean_t
411*8474SJose.Borrego@Sun.COM winreg_key_has_subkey(const char *subkey)
412*8474SJose.Borrego@Sun.COM {
413*8474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
414*8474SJose.Borrego@Sun.COM 	int keylen;
415*8474SJose.Borrego@Sun.COM 
416*8474SJose.Borrego@Sun.COM 	if (list_is_empty(&winreg_keylist.kl_list))
417*8474SJose.Borrego@Sun.COM 		return (B_FALSE);
418*8474SJose.Borrego@Sun.COM 
419*8474SJose.Borrego@Sun.COM 	keylen = strlen(subkey);
420*8474SJose.Borrego@Sun.COM 
421*8474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
422*8474SJose.Borrego@Sun.COM 	do {
423*8474SJose.Borrego@Sun.COM 		if (strncasecmp(subkey, key->sk_name, keylen) == 0) {
424*8474SJose.Borrego@Sun.COM 			/*
425*8474SJose.Borrego@Sun.COM 			 * Potential match.  If sk_name is longer than
426*8474SJose.Borrego@Sun.COM 			 * subkey, then sk_name is a subkey of our key.
427*8474SJose.Borrego@Sun.COM 			 */
428*8474SJose.Borrego@Sun.COM 			if (keylen < strlen(key->sk_name))
429*8474SJose.Borrego@Sun.COM 				return (B_TRUE);
430*8474SJose.Borrego@Sun.COM 		}
431*8474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
432*8474SJose.Borrego@Sun.COM 
433*8474SJose.Borrego@Sun.COM 	return (B_FALSE);
434*8474SJose.Borrego@Sun.COM }
435*8474SJose.Borrego@Sun.COM 
436*8474SJose.Borrego@Sun.COM /*
437*8474SJose.Borrego@Sun.COM  * winreg_subkey_get_relative_name
438*8474SJose.Borrego@Sun.COM  *
439*8474SJose.Borrego@Sun.COM  * Each key contains one or more child keys, each called a subkey.
440*8474SJose.Borrego@Sun.COM  * For any specified key, its name MUST be unique for any other subkeys that
441*8474SJose.Borrego@Sun.COM  * have the same parent key.
442*8474SJose.Borrego@Sun.COM  *
443*8474SJose.Borrego@Sun.COM  * To accurately identify a given subkey within the key namespace, its fully
444*8474SJose.Borrego@Sun.COM  * qualified name (FQN) is used. The FQN MUST consist of the name of the subkey
445*8474SJose.Borrego@Sun.COM  * and the name of all of its parent keys all the way to the root of the tree.
446*8474SJose.Borrego@Sun.COM  *
447*8474SJose.Borrego@Sun.COM  * The "\" character MUST be used as a hierarchy separator to identify each key
448*8474SJose.Borrego@Sun.COM  * in the FQN and therefore MUST not be used in the name of a single key.
449*8474SJose.Borrego@Sun.COM  * For example, the subkey "MountedDevices" belongs to the subtree
450*8474SJose.Borrego@Sun.COM  * HKEY_LOCAL_MACHINE, as shown in the following example.
451*8474SJose.Borrego@Sun.COM  *
452*8474SJose.Borrego@Sun.COM  *	HKEY_LOCAL_MACHINE -> SYSTEM -> MountedDevices
453*8474SJose.Borrego@Sun.COM  *
454*8474SJose.Borrego@Sun.COM  * The FQN for MountedDevices is HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices.
455*8474SJose.Borrego@Sun.COM  * The relative name of the subkey is "MountedDevices". The relative name
456*8474SJose.Borrego@Sun.COM  * MUST be used only for operations that are performed on its immediate parent
457*8474SJose.Borrego@Sun.COM  * key (SYSTEM in the previous example).
458*8474SJose.Borrego@Sun.COM  */
459*8474SJose.Borrego@Sun.COM static char *
460*8474SJose.Borrego@Sun.COM winreg_subkey_get_relative_name(const char *subkey)
461*8474SJose.Borrego@Sun.COM {
462*8474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
463*8474SJose.Borrego@Sun.COM 	char *value;
464*8474SJose.Borrego@Sun.COM 
465*8474SJose.Borrego@Sun.COM 	if (subkey == NULL)
466*8474SJose.Borrego@Sun.COM 		return (NULL);
467*8474SJose.Borrego@Sun.COM 
468*8474SJose.Borrego@Sun.COM 	if (list_is_empty(&winreg_keylist.kl_list))
469*8474SJose.Borrego@Sun.COM 		return (NULL);
470*8474SJose.Borrego@Sun.COM 
471*8474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
472*8474SJose.Borrego@Sun.COM 	do {
473*8474SJose.Borrego@Sun.COM 		if (strcasecmp(subkey, key->sk_name) == 0) {
474*8474SJose.Borrego@Sun.COM 			value = strrchr(key->sk_name, '\\');
475*8474SJose.Borrego@Sun.COM 			if (value != NULL)
476*8474SJose.Borrego@Sun.COM 				return (++value);
477*8474SJose.Borrego@Sun.COM 		}
478*8474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
479*8474SJose.Borrego@Sun.COM 
480*8474SJose.Borrego@Sun.COM 	return (NULL);
481*8474SJose.Borrego@Sun.COM }
482*8474SJose.Borrego@Sun.COM 
483*8474SJose.Borrego@Sun.COM /*
484*8474SJose.Borrego@Sun.COM  * winreg_s_DeleteValue
485*8474SJose.Borrego@Sun.COM  */
486*8474SJose.Borrego@Sun.COM /*ARGSUSED*/
487*8474SJose.Borrego@Sun.COM static int
488*8474SJose.Borrego@Sun.COM winreg_s_DeleteValue(void *arg, ndr_xa_t *mxa)
489*8474SJose.Borrego@Sun.COM {
490*8474SJose.Borrego@Sun.COM 	struct winreg_DeleteValue *param = arg;
491*8474SJose.Borrego@Sun.COM 
492*8474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
493*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
494*8474SJose.Borrego@Sun.COM }
495*8474SJose.Borrego@Sun.COM 
496*8474SJose.Borrego@Sun.COM /*
497*8474SJose.Borrego@Sun.COM  * winreg_s_EnumKey
498*8474SJose.Borrego@Sun.COM  */
499*8474SJose.Borrego@Sun.COM static int
500*8474SJose.Borrego@Sun.COM winreg_s_EnumKey(void *arg, ndr_xa_t *mxa)
501*8474SJose.Borrego@Sun.COM {
502*8474SJose.Borrego@Sun.COM 	struct winreg_EnumKey *param = arg;
503*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
504*8474SJose.Borrego@Sun.COM 	winreg_string_t	*name, *class;
505*8474SJose.Borrego@Sun.COM 	char *value, *namep = NULL, *classp = NULL;
506*8474SJose.Borrego@Sun.COM 	int slen = 0;
507*8474SJose.Borrego@Sun.COM 
508*8474SJose.Borrego@Sun.COM 	if (ndr_hdlookup(mxa, id) == NULL) {
509*8474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumKey));
510*8474SJose.Borrego@Sun.COM 		param->status = ERROR_NO_MORE_ITEMS;
511*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
512*8474SJose.Borrego@Sun.COM 	}
513*8474SJose.Borrego@Sun.COM 
514*8474SJose.Borrego@Sun.COM 	if (param->index > 0) {
515*8474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumKey));
516*8474SJose.Borrego@Sun.COM 		param->status = ERROR_NO_MORE_ITEMS;
517*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
518*8474SJose.Borrego@Sun.COM 	}
519*8474SJose.Borrego@Sun.COM 
520*8474SJose.Borrego@Sun.COM 	name = (winreg_string_t	*)&param->name_in;
521*8474SJose.Borrego@Sun.COM 	class = (winreg_string_t *)&param->class_in;
522*8474SJose.Borrego@Sun.COM 	if (name->length != 0)
523*8474SJose.Borrego@Sun.COM 		namep = (char *)name->str;
524*8474SJose.Borrego@Sun.COM 
525*8474SJose.Borrego@Sun.COM 	if (class->length != 0)
526*8474SJose.Borrego@Sun.COM 		classp = (char *)class->str;
527*8474SJose.Borrego@Sun.COM 
528*8474SJose.Borrego@Sun.COM 	value = winreg_lookup_eventlog_registry(namep, classp);
529*8474SJose.Borrego@Sun.COM 	if (value == NULL) {
530*8474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumKey));
531*8474SJose.Borrego@Sun.COM 		param->status = ERROR_CANTREAD;
532*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
533*8474SJose.Borrego@Sun.COM 	}
534*8474SJose.Borrego@Sun.COM 
535*8474SJose.Borrego@Sun.COM 	slen = mts_wcequiv_strlen(value) + sizeof (mts_wchar_t);
536*8474SJose.Borrego@Sun.COM 	param->name_out.length = slen;
537*8474SJose.Borrego@Sun.COM 	param->name_out.allosize = slen;
538*8474SJose.Borrego@Sun.COM 	if ((param->name_out.str = NDR_STRDUP(mxa, value)) == NULL) {
539*8474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumKey));
540*8474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
541*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
542*8474SJose.Borrego@Sun.COM 	}
543*8474SJose.Borrego@Sun.COM 
544*8474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
545*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
546*8474SJose.Borrego@Sun.COM }
547*8474SJose.Borrego@Sun.COM 
548*8474SJose.Borrego@Sun.COM /*
549*8474SJose.Borrego@Sun.COM  * winreg_s_EnumValue
550*8474SJose.Borrego@Sun.COM  */
551*8474SJose.Borrego@Sun.COM static int
552*8474SJose.Borrego@Sun.COM winreg_s_EnumValue(void *arg, ndr_xa_t *mxa)
553*8474SJose.Borrego@Sun.COM {
554*8474SJose.Borrego@Sun.COM 	struct winreg_EnumValue *param = arg;
555*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
556*8474SJose.Borrego@Sun.COM 
557*8474SJose.Borrego@Sun.COM 	if (ndr_hdlookup(mxa, id) == NULL) {
558*8474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_EnumValue));
559*8474SJose.Borrego@Sun.COM 		param->status = ERROR_NO_MORE_ITEMS;
560*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
561*8474SJose.Borrego@Sun.COM 	}
562*8474SJose.Borrego@Sun.COM 
563*8474SJose.Borrego@Sun.COM 	bzero(param, sizeof (struct winreg_EnumValue));
564*8474SJose.Borrego@Sun.COM 	param->status = ERROR_NO_MORE_ITEMS;
565*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
566*8474SJose.Borrego@Sun.COM }
567*8474SJose.Borrego@Sun.COM 
568*8474SJose.Borrego@Sun.COM /*
569*8474SJose.Borrego@Sun.COM  * winreg_s_FlushKey
570*8474SJose.Borrego@Sun.COM  *
571*8474SJose.Borrego@Sun.COM  * Flush the attributes associated with the specified open key to disk.
572*8474SJose.Borrego@Sun.COM  */
573*8474SJose.Borrego@Sun.COM static int
574*8474SJose.Borrego@Sun.COM winreg_s_FlushKey(void *arg, ndr_xa_t *mxa)
575*8474SJose.Borrego@Sun.COM {
576*8474SJose.Borrego@Sun.COM 	struct winreg_FlushKey *param = arg;
577*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
578*8474SJose.Borrego@Sun.COM 
579*8474SJose.Borrego@Sun.COM 	if (ndr_hdlookup(mxa, id) == NULL)
580*8474SJose.Borrego@Sun.COM 		param->status = ERROR_INVALID_HANDLE;
581*8474SJose.Borrego@Sun.COM 	else
582*8474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
583*8474SJose.Borrego@Sun.COM 
584*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
585*8474SJose.Borrego@Sun.COM }
586*8474SJose.Borrego@Sun.COM 
587*8474SJose.Borrego@Sun.COM /*
588*8474SJose.Borrego@Sun.COM  * winreg_s_GetKeySec
589*8474SJose.Borrego@Sun.COM  */
590*8474SJose.Borrego@Sun.COM /*ARGSUSED*/
591*8474SJose.Borrego@Sun.COM static int
592*8474SJose.Borrego@Sun.COM winreg_s_GetKeySec(void *arg, ndr_xa_t *mxa)
593*8474SJose.Borrego@Sun.COM {
594*8474SJose.Borrego@Sun.COM 	struct winreg_GetKeySec *param = arg;
595*8474SJose.Borrego@Sun.COM 
596*8474SJose.Borrego@Sun.COM 	bzero(param, sizeof (struct winreg_GetKeySec));
597*8474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
598*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
599*8474SJose.Borrego@Sun.COM }
600*8474SJose.Borrego@Sun.COM 
601*8474SJose.Borrego@Sun.COM /*
602*8474SJose.Borrego@Sun.COM  * winreg_s_NotifyChange
603*8474SJose.Borrego@Sun.COM  */
604*8474SJose.Borrego@Sun.COM static int
605*8474SJose.Borrego@Sun.COM winreg_s_NotifyChange(void *arg, ndr_xa_t *mxa)
606*8474SJose.Borrego@Sun.COM {
607*8474SJose.Borrego@Sun.COM 	struct winreg_NotifyChange *param = arg;
608*8474SJose.Borrego@Sun.COM 
609*8474SJose.Borrego@Sun.COM 	if (ndr_is_admin(mxa))
610*8474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
611*8474SJose.Borrego@Sun.COM 	else
612*8474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
613*8474SJose.Borrego@Sun.COM 
614*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
615*8474SJose.Borrego@Sun.COM }
616*8474SJose.Borrego@Sun.COM 
617*8474SJose.Borrego@Sun.COM /*
618*8474SJose.Borrego@Sun.COM  * winreg_s_OpenKey
619*8474SJose.Borrego@Sun.COM  *
620*8474SJose.Borrego@Sun.COM  * This is a request to open a windows registry key.
621*8474SJose.Borrego@Sun.COM  * If we recognize the key, we return a handle.
622*8474SJose.Borrego@Sun.COM  *
623*8474SJose.Borrego@Sun.COM  * Returns:
624*8474SJose.Borrego@Sun.COM  *	ERROR_SUCCESS		Valid handle returned.
625*8474SJose.Borrego@Sun.COM  *	ERROR_FILE_NOT_FOUND	No key or unable to allocate a handle.
626*8474SJose.Borrego@Sun.COM  */
627*8474SJose.Borrego@Sun.COM static int
628*8474SJose.Borrego@Sun.COM winreg_s_OpenKey(void *arg, ndr_xa_t *mxa)
629*8474SJose.Borrego@Sun.COM {
630*8474SJose.Borrego@Sun.COM 	struct winreg_OpenKey *param = arg;
631*8474SJose.Borrego@Sun.COM 	char *subkey = (char *)param->name.str;
632*8474SJose.Borrego@Sun.COM 	ndr_hdid_t *id = NULL;
633*8474SJose.Borrego@Sun.COM 	winreg_subkey_t *key;
634*8474SJose.Borrego@Sun.COM 
635*8474SJose.Borrego@Sun.COM 	if (list_is_empty(&winreg_keylist.kl_list)) {
636*8474SJose.Borrego@Sun.COM 		bzero(&param->result_handle, sizeof (winreg_handle_t));
637*8474SJose.Borrego@Sun.COM 		param->status = ERROR_FILE_NOT_FOUND;
638*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
639*8474SJose.Borrego@Sun.COM 	}
640*8474SJose.Borrego@Sun.COM 
641*8474SJose.Borrego@Sun.COM 	key = list_head(&winreg_keylist.kl_list);
642*8474SJose.Borrego@Sun.COM 	do {
643*8474SJose.Borrego@Sun.COM 		if (strcasecmp(subkey, key->sk_name) == 0) {
644*8474SJose.Borrego@Sun.COM 			if (key->sk_predefined == B_TRUE)
645*8474SJose.Borrego@Sun.COM 				id = ndr_hdalloc(mxa, &winreg_hkkey);
646*8474SJose.Borrego@Sun.COM 			else
647*8474SJose.Borrego@Sun.COM 				id = &key->sk_handle;
648*8474SJose.Borrego@Sun.COM 
649*8474SJose.Borrego@Sun.COM 			if (id == NULL)
650*8474SJose.Borrego@Sun.COM 				break;
651*8474SJose.Borrego@Sun.COM 
652*8474SJose.Borrego@Sun.COM 			bcopy(id, &param->result_handle,
653*8474SJose.Borrego@Sun.COM 			    sizeof (winreg_handle_t));
654*8474SJose.Borrego@Sun.COM 			param->status = ERROR_SUCCESS;
655*8474SJose.Borrego@Sun.COM 			return (NDR_DRC_OK);
656*8474SJose.Borrego@Sun.COM 		}
657*8474SJose.Borrego@Sun.COM 	} while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
658*8474SJose.Borrego@Sun.COM 
659*8474SJose.Borrego@Sun.COM 	bzero(&param->result_handle, sizeof (winreg_handle_t));
660*8474SJose.Borrego@Sun.COM 	param->status = ERROR_FILE_NOT_FOUND;
661*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
662*8474SJose.Borrego@Sun.COM }
663*8474SJose.Borrego@Sun.COM 
664*8474SJose.Borrego@Sun.COM /*
665*8474SJose.Borrego@Sun.COM  * winreg_s_QueryKey
666*8474SJose.Borrego@Sun.COM  */
667*8474SJose.Borrego@Sun.COM /*ARGSUSED*/
668*8474SJose.Borrego@Sun.COM static int
669*8474SJose.Borrego@Sun.COM winreg_s_QueryKey(void *arg, ndr_xa_t *mxa)
670*8474SJose.Borrego@Sun.COM {
671*8474SJose.Borrego@Sun.COM 	struct winreg_QueryKey *param = arg;
672*8474SJose.Borrego@Sun.COM 	int rc;
673*8474SJose.Borrego@Sun.COM 	winreg_string_t	*name;
674*8474SJose.Borrego@Sun.COM 
675*8474SJose.Borrego@Sun.COM 	name = (winreg_string_t	*)&param->name;
676*8474SJose.Borrego@Sun.COM 	bzero(param, sizeof (struct winreg_QueryKey));
677*8474SJose.Borrego@Sun.COM 	if ((name = NDR_NEW(mxa, winreg_string_t)) != NULL)
678*8474SJose.Borrego@Sun.COM 		rc = NDR_MSTRING(mxa, "", (ndr_mstring_t *)name);
679*8474SJose.Borrego@Sun.COM 
680*8474SJose.Borrego@Sun.COM 	if ((name == NULL) || (rc != 0)) {
681*8474SJose.Borrego@Sun.COM 		bzero(param, sizeof (struct winreg_QueryKey));
682*8474SJose.Borrego@Sun.COM 		param->status = ERROR_NOT_ENOUGH_MEMORY;
683*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
684*8474SJose.Borrego@Sun.COM 	}
685*8474SJose.Borrego@Sun.COM 
686*8474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
687*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
688*8474SJose.Borrego@Sun.COM }
689*8474SJose.Borrego@Sun.COM 
690*8474SJose.Borrego@Sun.COM /*
691*8474SJose.Borrego@Sun.COM  * winreg_s_QueryValue
692*8474SJose.Borrego@Sun.COM  *
693*8474SJose.Borrego@Sun.COM  * This is a request to get the value associated with a specified name.
694*8474SJose.Borrego@Sun.COM  *
695*8474SJose.Borrego@Sun.COM  * Returns:
696*8474SJose.Borrego@Sun.COM  *	ERROR_SUCCESS		Value returned.
697*8474SJose.Borrego@Sun.COM  *	ERROR_FILE_NOT_FOUND	PrimaryModule is not supported.
698*8474SJose.Borrego@Sun.COM  *	ERROR_CANTREAD          No such name or memory problem.
699*8474SJose.Borrego@Sun.COM  */
700*8474SJose.Borrego@Sun.COM static int
701*8474SJose.Borrego@Sun.COM winreg_s_QueryValue(void *arg, ndr_xa_t *mxa)
702*8474SJose.Borrego@Sun.COM {
703*8474SJose.Borrego@Sun.COM 	struct winreg_QueryValue *param = arg;
704*8474SJose.Borrego@Sun.COM 	struct winreg_value *pv;
705*8474SJose.Borrego@Sun.COM 	char *name;
706*8474SJose.Borrego@Sun.COM 	char *value;
707*8474SJose.Borrego@Sun.COM 	DWORD slen;
708*8474SJose.Borrego@Sun.COM 	DWORD msize;
709*8474SJose.Borrego@Sun.COM 
710*8474SJose.Borrego@Sun.COM 	name = (char *)param->value_name.str;
711*8474SJose.Borrego@Sun.COM 
712*8474SJose.Borrego@Sun.COM 	if (strcasecmp(name, "PrimaryModule") == 0) {
713*8474SJose.Borrego@Sun.COM 		param->status = ERROR_FILE_NOT_FOUND;
714*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
715*8474SJose.Borrego@Sun.COM 	}
716*8474SJose.Borrego@Sun.COM 
717*8474SJose.Borrego@Sun.COM 	if ((value = winreg_lookup_value(name)) == NULL) {
718*8474SJose.Borrego@Sun.COM 		param->status = ERROR_CANTREAD;
719*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
720*8474SJose.Borrego@Sun.COM 	}
721*8474SJose.Borrego@Sun.COM 
722*8474SJose.Borrego@Sun.COM 	slen = mts_wcequiv_strlen(value) + sizeof (mts_wchar_t);
723*8474SJose.Borrego@Sun.COM 	msize = sizeof (struct winreg_value) + slen;
724*8474SJose.Borrego@Sun.COM 
725*8474SJose.Borrego@Sun.COM 	param->value = (struct winreg_value *)NDR_MALLOC(mxa, msize);
726*8474SJose.Borrego@Sun.COM 	param->type = NDR_NEW(mxa, DWORD);
727*8474SJose.Borrego@Sun.COM 	param->value_size = NDR_NEW(mxa, DWORD);
728*8474SJose.Borrego@Sun.COM 	param->value_size_total = NDR_NEW(mxa, DWORD);
729*8474SJose.Borrego@Sun.COM 
730*8474SJose.Borrego@Sun.COM 	if (param->value == NULL || param->type == NULL ||
731*8474SJose.Borrego@Sun.COM 	    param->value_size == NULL || param->value_size_total == NULL) {
732*8474SJose.Borrego@Sun.COM 		param->status = ERROR_CANTREAD;
733*8474SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
734*8474SJose.Borrego@Sun.COM 	}
735*8474SJose.Borrego@Sun.COM 
736*8474SJose.Borrego@Sun.COM 	bzero(param->value, msize);
737*8474SJose.Borrego@Sun.COM 	pv = param->value;
738*8474SJose.Borrego@Sun.COM 	pv->vc_first_is = 0;
739*8474SJose.Borrego@Sun.COM 	pv->vc_length_is = slen;
740*8474SJose.Borrego@Sun.COM 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
741*8474SJose.Borrego@Sun.COM 	(void) ndr_mbstowcs(NULL, (mts_wchar_t *)pv->value, value, slen);
742*8474SJose.Borrego@Sun.COM 
743*8474SJose.Borrego@Sun.COM 	*param->type = 1;
744*8474SJose.Borrego@Sun.COM 	*param->value_size = slen;
745*8474SJose.Borrego@Sun.COM 	*param->value_size_total = slen;
746*8474SJose.Borrego@Sun.COM 
747*8474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
748*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
749*8474SJose.Borrego@Sun.COM }
750*8474SJose.Borrego@Sun.COM 
751*8474SJose.Borrego@Sun.COM /*
752*8474SJose.Borrego@Sun.COM  * Lookup a name in the registry and return the associated value.
753*8474SJose.Borrego@Sun.COM  * Our registry is a case-insensitive, name-value pair table.
754*8474SJose.Borrego@Sun.COM  *
755*8474SJose.Borrego@Sun.COM  * Windows ProductType: WinNT, ServerNT, LanmanNT.
756*8474SJose.Borrego@Sun.COM  *	Windows NT4.0 workstation: WinNT
757*8474SJose.Borrego@Sun.COM  *	Windows NT4.0 server:      ServerNT
758*8474SJose.Borrego@Sun.COM  *
759*8474SJose.Borrego@Sun.COM  * If LanmanNT is used here, Windows 2000 sends LsarQueryInfoPolicy
760*8474SJose.Borrego@Sun.COM  * with info level 6, which we don't support.  If we use ServerNT
761*8474SJose.Borrego@Sun.COM  * (as reported by NT4.0 Server) Windows 2000 send requests for
762*8474SJose.Borrego@Sun.COM  * levels 3 and 5, which are support.
763*8474SJose.Borrego@Sun.COM  *
764*8474SJose.Borrego@Sun.COM  * On success, returns a pointer to the value.  Otherwise returns
765*8474SJose.Borrego@Sun.COM  * a null pointer.
766*8474SJose.Borrego@Sun.COM  */
767*8474SJose.Borrego@Sun.COM static char *
768*8474SJose.Borrego@Sun.COM winreg_lookup_value(const char *name)
769*8474SJose.Borrego@Sun.COM {
770*8474SJose.Borrego@Sun.COM 	static struct registry {
771*8474SJose.Borrego@Sun.COM 		char *name;
772*8474SJose.Borrego@Sun.COM 		char *value;
773*8474SJose.Borrego@Sun.COM 	} registry[] = {
774*8474SJose.Borrego@Sun.COM 		{ "ProductType", "ServerNT" },
775*8474SJose.Borrego@Sun.COM 		{ "Sources",	 NULL }	/* product name */
776*8474SJose.Borrego@Sun.COM 	};
777*8474SJose.Borrego@Sun.COM 
778*8474SJose.Borrego@Sun.COM 	int i;
779*8474SJose.Borrego@Sun.COM 
780*8474SJose.Borrego@Sun.COM 	for (i = 0; i < sizeof (registry)/sizeof (registry[0]); ++i) {
781*8474SJose.Borrego@Sun.COM 		if (strcasecmp(registry[i].name, name) == 0) {
782*8474SJose.Borrego@Sun.COM 			if (registry[i].value == NULL)
783*8474SJose.Borrego@Sun.COM 				return (winreg_sysname);
784*8474SJose.Borrego@Sun.COM 			else
785*8474SJose.Borrego@Sun.COM 				return (registry[i].value);
786*8474SJose.Borrego@Sun.COM 		}
787*8474SJose.Borrego@Sun.COM 	}
788*8474SJose.Borrego@Sun.COM 
789*8474SJose.Borrego@Sun.COM 	return (NULL);
790*8474SJose.Borrego@Sun.COM }
791*8474SJose.Borrego@Sun.COM 
792*8474SJose.Borrego@Sun.COM /*
793*8474SJose.Borrego@Sun.COM  * winreg_lookup_eventlog_registry
794*8474SJose.Borrego@Sun.COM  *
795*8474SJose.Borrego@Sun.COM  * Return the subkey of the specified EventLog key. Decoding of
796*8474SJose.Borrego@Sun.COM  * class paramater not yet supported.
797*8474SJose.Borrego@Sun.COM  */
798*8474SJose.Borrego@Sun.COM /*ARGSUSED*/
799*8474SJose.Borrego@Sun.COM static char *
800*8474SJose.Borrego@Sun.COM winreg_lookup_eventlog_registry(char *name, char *class)
801*8474SJose.Borrego@Sun.COM {
802*8474SJose.Borrego@Sun.COM 	if (name == NULL)
803*8474SJose.Borrego@Sun.COM 		return (winreg_subkey_get_relative_name(WINREG_LOGR_SYSTEMKEY));
804*8474SJose.Borrego@Sun.COM 
805*8474SJose.Borrego@Sun.COM 	return (winreg_subkey_get_relative_name(name));
806*8474SJose.Borrego@Sun.COM }
807*8474SJose.Borrego@Sun.COM 
808*8474SJose.Borrego@Sun.COM /*
809*8474SJose.Borrego@Sun.COM  * winreg_s_SetKeySec
810*8474SJose.Borrego@Sun.COM  */
811*8474SJose.Borrego@Sun.COM /*ARGSUSED*/
812*8474SJose.Borrego@Sun.COM static int
813*8474SJose.Borrego@Sun.COM winreg_s_SetKeySec(void *arg, ndr_xa_t *mxa)
814*8474SJose.Borrego@Sun.COM {
815*8474SJose.Borrego@Sun.COM 	struct winreg_SetKeySec *param = arg;
816*8474SJose.Borrego@Sun.COM 
817*8474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
818*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
819*8474SJose.Borrego@Sun.COM }
820*8474SJose.Borrego@Sun.COM 
821*8474SJose.Borrego@Sun.COM /*
822*8474SJose.Borrego@Sun.COM  * winreg_s_CreateValue
823*8474SJose.Borrego@Sun.COM  */
824*8474SJose.Borrego@Sun.COM /*ARGSUSED*/
825*8474SJose.Borrego@Sun.COM static int
826*8474SJose.Borrego@Sun.COM winreg_s_CreateValue(void *arg, ndr_xa_t *mxa)
827*8474SJose.Borrego@Sun.COM {
828*8474SJose.Borrego@Sun.COM 	struct winreg_CreateValue *param = arg;
829*8474SJose.Borrego@Sun.COM 
830*8474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
831*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
832*8474SJose.Borrego@Sun.COM }
833*8474SJose.Borrego@Sun.COM 
834*8474SJose.Borrego@Sun.COM /*
835*8474SJose.Borrego@Sun.COM  * winreg_s_Shutdown
836*8474SJose.Borrego@Sun.COM  *
837*8474SJose.Borrego@Sun.COM  * Attempt to shutdown or reboot the system: access denied.
838*8474SJose.Borrego@Sun.COM  */
839*8474SJose.Borrego@Sun.COM /*ARGSUSED*/
840*8474SJose.Borrego@Sun.COM static int
841*8474SJose.Borrego@Sun.COM winreg_s_Shutdown(void *arg, ndr_xa_t *mxa)
842*8474SJose.Borrego@Sun.COM {
843*8474SJose.Borrego@Sun.COM 	struct winreg_Shutdown *param = arg;
844*8474SJose.Borrego@Sun.COM 
845*8474SJose.Borrego@Sun.COM 	param->status = ERROR_ACCESS_DENIED;
846*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
847*8474SJose.Borrego@Sun.COM }
848*8474SJose.Borrego@Sun.COM 
849*8474SJose.Borrego@Sun.COM /*
850*8474SJose.Borrego@Sun.COM  * winreg_s_AbortShutdown
851*8474SJose.Borrego@Sun.COM  *
852*8474SJose.Borrego@Sun.COM  * Abort a shutdown request.
853*8474SJose.Borrego@Sun.COM  */
854*8474SJose.Borrego@Sun.COM static int
855*8474SJose.Borrego@Sun.COM winreg_s_AbortShutdown(void *arg, ndr_xa_t *mxa)
856*8474SJose.Borrego@Sun.COM {
857*8474SJose.Borrego@Sun.COM 	struct winreg_AbortShutdown *param = arg;
858*8474SJose.Borrego@Sun.COM 
859*8474SJose.Borrego@Sun.COM 	if (ndr_is_admin(mxa))
860*8474SJose.Borrego@Sun.COM 		param->status = ERROR_SUCCESS;
861*8474SJose.Borrego@Sun.COM 	else
862*8474SJose.Borrego@Sun.COM 		param->status = ERROR_ACCESS_DENIED;
863*8474SJose.Borrego@Sun.COM 
864*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
865*8474SJose.Borrego@Sun.COM }
866*8474SJose.Borrego@Sun.COM 
867*8474SJose.Borrego@Sun.COM /*
868*8474SJose.Borrego@Sun.COM  * winreg_s_GetVersion
869*8474SJose.Borrego@Sun.COM  *
870*8474SJose.Borrego@Sun.COM  * Return the windows registry version.  The current version is 5.
871*8474SJose.Borrego@Sun.COM  * This call is usually made prior to enumerating or querying registry
872*8474SJose.Borrego@Sun.COM  * keys or values.
873*8474SJose.Borrego@Sun.COM  */
874*8474SJose.Borrego@Sun.COM /*ARGSUSED*/
875*8474SJose.Borrego@Sun.COM static int
876*8474SJose.Borrego@Sun.COM winreg_s_GetVersion(void *arg, ndr_xa_t *mxa)
877*8474SJose.Borrego@Sun.COM {
878*8474SJose.Borrego@Sun.COM 	struct winreg_GetVersion *param = arg;
879*8474SJose.Borrego@Sun.COM 
880*8474SJose.Borrego@Sun.COM 	param->version = 5;
881*8474SJose.Borrego@Sun.COM 	param->status = ERROR_SUCCESS;
882*8474SJose.Borrego@Sun.COM 	return (NDR_DRC_OK);
883*8474SJose.Borrego@Sun.COM }
884