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