smbd: Fix crossing automounter mount points
[Samba.git] / source3 / rpc_server / winreg / srv_winreg_nt.c
blob132213a6e863da5e054cac003978e282824376f2
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
5 * Copyright (C) Gerald Carter 2002-2006.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 /* Implementation of registry functions. */
23 #include "includes.h"
24 #include "ntdomain.h"
25 #include "librpc/rpc/dcesrv_core.h"
26 #include "librpc/gen_ndr/ndr_winreg.h"
27 #include "librpc/gen_ndr/ndr_winreg_scompat.h"
28 #include "registry.h"
29 #include "registry/reg_api.h"
30 #include "registry/reg_perfcount.h"
31 #include "rpc_misc.h"
32 #include "auth.h"
33 #include "lib/privileges.h"
34 #include "libcli/security/secdesc.h"
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_RPC_SRV
39 enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY };
41 /******************************************************************
42 Find a registry key handle and return a struct registry_key *
43 *****************************************************************/
45 static struct registry_key *find_regkey_by_hnd(struct pipes_struct *p,
46 struct policy_handle *hnd,
47 enum handle_types type)
49 struct registry_key *regkey = NULL;
50 NTSTATUS status;
52 regkey = find_policy_by_hnd(p,
53 hnd,
54 type,
55 struct registry_key,
56 &status);
57 if (!NT_STATUS_IS_OK(status)) {
58 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: %s\n",
59 nt_errstr(status)));
60 return NULL;
63 return regkey;
66 /*******************************************************************
67 Function for open a new registry handle and creating a handle
68 Note that P should be valid & hnd should already have space
70 When we open a key, we store the full path to the key as
71 HK[LM|U]\<key>\<key>\...
72 *******************************************************************/
74 static WERROR open_registry_key(struct pipes_struct *p,
75 struct policy_handle *hnd,
76 struct registry_key *parent,
77 const char *subkeyname,
78 uint32_t access_desired)
80 struct dcesrv_call_state *dce_call = p->dce_call;
81 struct auth_session_info *session_info =
82 dcesrv_call_session_info(dce_call);
83 WERROR result = WERR_OK;
84 struct registry_key *key;
86 if (parent == NULL) {
87 result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
88 session_info->security_token, &key);
90 else {
91 result = reg_openkey(p->mem_ctx, parent, subkeyname,
92 access_desired, &key);
95 if ( !W_ERROR_IS_OK(result) ) {
96 return result;
99 if ( !create_policy_hnd( p, hnd, HTYPE_REGKEY, key ) ) {
100 return WERR_FILE_NOT_FOUND;
103 return WERR_OK;
106 /*******************************************************************
107 Function for open a new registry handle and creating a handle
108 Note that P should be valid & hnd should already have space
109 *******************************************************************/
111 static bool close_registry_key(struct pipes_struct *p,
112 struct policy_handle *hnd,
113 enum handle_types type)
115 struct registry_key *regkey = find_regkey_by_hnd(p, hnd, type);
117 if ( !regkey ) {
118 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
119 OUR_HANDLE(hnd)));
120 return False;
123 close_policy_hnd(p, hnd);
125 return True;
128 /********************************************************************
129 _winreg_CloseKey
130 ********************************************************************/
132 WERROR _winreg_CloseKey(struct pipes_struct *p,
133 struct winreg_CloseKey *r)
135 bool ok;
137 /* close the policy handle */
139 ok = close_registry_key(p, r->in.handle, HTYPE_REGKEY);
140 if (!ok) {
141 return WERR_INVALID_HANDLE;
144 ZERO_STRUCTP(r->out.handle);
146 return WERR_OK;
149 /*******************************************************************
150 _winreg_OpenHKLM
151 ********************************************************************/
153 WERROR _winreg_OpenHKLM(struct pipes_struct *p,
154 struct winreg_OpenHKLM *r)
156 return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
159 /*******************************************************************
160 _winreg_OpenHKPD
161 ********************************************************************/
163 WERROR _winreg_OpenHKPD(struct pipes_struct *p,
164 struct winreg_OpenHKPD *r)
166 return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
169 /*******************************************************************
170 _winreg_OpenHKPT
171 ********************************************************************/
173 WERROR _winreg_OpenHKPT(struct pipes_struct *p,
174 struct winreg_OpenHKPT *r)
176 return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
179 /*******************************************************************
180 _winreg_OpenHKCR
181 ********************************************************************/
183 WERROR _winreg_OpenHKCR(struct pipes_struct *p,
184 struct winreg_OpenHKCR *r)
186 return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
189 /*******************************************************************
190 _winreg_OpenHKU
191 ********************************************************************/
193 WERROR _winreg_OpenHKU(struct pipes_struct *p,
194 struct winreg_OpenHKU *r)
196 return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
199 /*******************************************************************
200 _winreg_OpenHKCU
201 ********************************************************************/
203 WERROR _winreg_OpenHKCU(struct pipes_struct *p,
204 struct winreg_OpenHKCU *r)
206 return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
209 /*******************************************************************
210 _winreg_OpenHKCC
211 ********************************************************************/
213 WERROR _winreg_OpenHKCC(struct pipes_struct *p,
214 struct winreg_OpenHKCC *r)
216 return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
219 /*******************************************************************
220 _winreg_OpenHKDD
221 ********************************************************************/
223 WERROR _winreg_OpenHKDD(struct pipes_struct *p,
224 struct winreg_OpenHKDD *r)
226 return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
229 /*******************************************************************
230 _winreg_OpenHKPN
231 ********************************************************************/
233 WERROR _winreg_OpenHKPN(struct pipes_struct *p,
234 struct winreg_OpenHKPN *r)
236 return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
239 /*******************************************************************
240 _winreg_OpenKey
241 ********************************************************************/
243 WERROR _winreg_OpenKey(struct pipes_struct *p,
244 struct winreg_OpenKey *r)
246 struct registry_key *parent = find_regkey_by_hnd(p,
247 r->in.parent_handle,
248 HTYPE_REGKEY);
250 if ( !parent )
251 return WERR_INVALID_HANDLE;
253 return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
256 /*******************************************************************
257 _winreg_QueryValue
258 ********************************************************************/
260 WERROR _winreg_QueryValue(struct pipes_struct *p,
261 struct winreg_QueryValue *r)
263 WERROR status = WERR_FILE_NOT_FOUND;
264 struct registry_key *regkey = find_regkey_by_hnd(p,
265 r->in.handle,
266 HTYPE_REGKEY);
267 prs_struct prs_hkpd;
269 uint8_t *outbuf = NULL;
270 uint32_t outbuf_size = 0;
272 bool free_buf = False;
273 bool free_prs = False;
275 if ( !regkey )
276 return WERR_INVALID_HANDLE;
278 if (r->in.value_name->name == NULL) {
279 return WERR_INVALID_PARAMETER;
282 if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
283 return WERR_INVALID_PARAMETER;
286 DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
287 DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
289 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
290 if(regkey->key->type == REG_KEY_HKPD)
292 if (strequal(r->in.value_name->name, "Global")) {
293 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
294 return WERR_NOT_ENOUGH_MEMORY;
295 status = reg_perfcount_get_hkpd(
296 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
297 outbuf = (uint8_t *)prs_hkpd.data_p;
298 free_prs = True;
300 else if (strequal(r->in.value_name->name, "Counter 009")) {
301 outbuf_size = reg_perfcount_get_counter_names(
302 reg_perfcount_get_base_index(),
303 (char **)(void *)&outbuf);
304 free_buf = True;
306 else if (strequal(r->in.value_name->name, "Explain 009")) {
307 outbuf_size = reg_perfcount_get_counter_help(
308 reg_perfcount_get_base_index(),
309 (char **)(void *)&outbuf);
310 free_buf = True;
312 else if (isdigit(r->in.value_name->name[0])) {
313 /* we probably have a request for a specific object
314 * here */
315 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
316 return WERR_NOT_ENOUGH_MEMORY;
317 status = reg_perfcount_get_hkpd(
318 &prs_hkpd, *r->in.data_size, &outbuf_size,
319 r->in.value_name->name);
320 outbuf = (uint8_t *)prs_hkpd.data_p;
321 free_prs = True;
323 else {
324 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
325 r->in.value_name->name));
326 return WERR_FILE_NOT_FOUND;
329 *r->out.type = REG_BINARY;
331 else {
332 struct registry_value *val;
334 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
335 &val);
336 if (!W_ERROR_IS_OK(status)) {
338 DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
339 win_errstr(status)));
341 if (r->out.data_size) {
342 *r->out.data_size = 0;
344 if (r->out.data_length) {
345 *r->out.data_length = 0;
347 return status;
350 outbuf = val->data.data;
351 outbuf_size = val->data.length;
352 *r->out.type = val->type;
355 status = WERR_FILE_NOT_FOUND;
357 if (*r->in.data_size < outbuf_size) {
358 *r->out.data_size = outbuf_size;
359 status = r->in.data ? WERR_MORE_DATA : WERR_OK;
360 } else {
361 *r->out.data_length = outbuf_size;
362 *r->out.data_size = outbuf_size;
363 if (r->out.data) {
364 memcpy(r->out.data, outbuf, outbuf_size);
366 status = WERR_OK;
369 if (free_prs) prs_mem_free(&prs_hkpd);
370 if (free_buf) SAFE_FREE(outbuf);
372 return status;
375 /*****************************************************************************
376 _winreg_QueryInfoKey
377 ****************************************************************************/
379 WERROR _winreg_QueryInfoKey(struct pipes_struct *p,
380 struct winreg_QueryInfoKey *r)
382 WERROR status = WERR_OK;
383 struct registry_key *regkey = find_regkey_by_hnd(p,
384 r->in.handle,
385 HTYPE_REGKEY);
387 if ( !regkey )
388 return WERR_INVALID_HANDLE;
390 r->out.classname->name = NULL;
392 status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
393 r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
394 r->out.max_valbufsize, r->out.secdescsize,
395 r->out.last_changed_time);
396 if (!W_ERROR_IS_OK(status)) {
397 return status;
401 * These calculations account for the registry buffers being
402 * UTF-16. They are inexact at best, but so far they worked.
405 *r->out.max_subkeylen *= 2;
407 *r->out.max_valnamelen += 1;
408 *r->out.max_valnamelen *= 2;
410 return WERR_OK;
414 /*****************************************************************************
415 _winreg_GetVersion
416 ****************************************************************************/
418 WERROR _winreg_GetVersion(struct pipes_struct *p,
419 struct winreg_GetVersion *r)
421 struct registry_key *regkey = find_regkey_by_hnd(p,
422 r->in.handle,
423 HTYPE_REGKEY);
425 if ( !regkey )
426 return WERR_INVALID_HANDLE;
428 return reg_getversion(r->out.version);
432 /*****************************************************************************
433 _winreg_EnumKey
434 ****************************************************************************/
436 WERROR _winreg_EnumKey(struct pipes_struct *p,
437 struct winreg_EnumKey *r)
439 WERROR err = WERR_OK;
440 struct registry_key *key = find_regkey_by_hnd(p,
441 r->in.handle,
442 HTYPE_REGKEY);
443 char *name;
445 if ( !key )
446 return WERR_INVALID_HANDLE;
448 if ( !r->in.name || !r->in.keyclass )
449 return WERR_INVALID_PARAMETER;
451 DEBUG(8,("_winreg_EnumKey: enumerating key [%s]\n", key->key->name));
453 err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, &name,
454 r->out.last_changed_time);
455 if (!W_ERROR_IS_OK(err)) {
456 return err;
458 r->out.name->name = name;
459 r->out.keyclass->name = "";
460 return WERR_OK;
463 /*****************************************************************************
464 _winreg_EnumValue
465 ****************************************************************************/
467 WERROR _winreg_EnumValue(struct pipes_struct *p,
468 struct winreg_EnumValue *r)
470 WERROR err = WERR_OK;
471 struct registry_key *key = find_regkey_by_hnd(p,
472 r->in.handle,
473 HTYPE_REGKEY);
474 char *valname = NULL;
475 struct registry_value *val = NULL;
477 if ( !key )
478 return WERR_INVALID_HANDLE;
480 if ( !r->in.name )
481 return WERR_INVALID_PARAMETER;
483 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
484 key->key->name));
486 err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
487 if (!W_ERROR_IS_OK(err)) {
488 return err;
491 if (r->out.name != NULL) {
492 r->out.name->name = valname;
495 if (r->out.type != NULL) {
496 *r->out.type = val->type;
499 if (r->out.value != NULL) {
500 if ((r->out.size == NULL) || (r->out.length == NULL)) {
501 return WERR_INVALID_PARAMETER;
504 if (val->data.length > *r->out.size) {
505 *r->out.size = val->data.length;
506 return WERR_MORE_DATA;
509 memcpy( r->out.value, val->data.data, val->data.length );
512 if (r->out.length != NULL) {
513 *r->out.length = val->data.length;
515 if (r->out.size != NULL) {
516 *r->out.size = val->data.length;
519 return WERR_OK;
522 /*******************************************************************
523 _winreg_InitiateSystemShutdown
524 ********************************************************************/
526 WERROR _winreg_InitiateSystemShutdown(struct pipes_struct *p,
527 struct winreg_InitiateSystemShutdown *r)
529 struct winreg_InitiateSystemShutdownEx s;
531 s.in.hostname = r->in.hostname;
532 s.in.message = r->in.message;
533 s.in.timeout = r->in.timeout;
534 s.in.force_apps = r->in.force_apps;
535 s.in.do_reboot = r->in.do_reboot;
536 s.in.reason = 0;
538 /* thunk down to _winreg_InitiateSystemShutdownEx()
539 (just returns a status) */
541 return _winreg_InitiateSystemShutdownEx( p, &s );
544 /*******************************************************************
545 _winreg_InitiateSystemShutdownEx
546 ********************************************************************/
548 #define SHUTDOWN_R_STRING "-r"
549 #define SHUTDOWN_F_STRING "-f"
552 WERROR _winreg_InitiateSystemShutdownEx(struct pipes_struct *p,
553 struct winreg_InitiateSystemShutdownEx *r)
555 struct dcesrv_call_state *dce_call = p->dce_call;
556 struct auth_session_info *session_info =
557 dcesrv_call_session_info(dce_call);
558 const struct loadparm_substitution *lp_sub =
559 loadparm_s3_global_substitution();
560 char *shutdown_script = NULL;
561 char *chkmsg = NULL;
562 fstring str_timeout;
563 fstring str_reason;
564 fstring do_reboot;
565 fstring f;
566 int ret = -1;
567 bool can_shutdown = false;
569 shutdown_script = lp_shutdown_script(p->mem_ctx, lp_sub);
570 if (!shutdown_script) {
571 return WERR_NOT_ENOUGH_MEMORY;
573 if (!*shutdown_script) {
574 return WERR_ACCESS_DENIED;
577 /* pull the message string and perform necessary sanity checks on it */
579 if ( r->in.message && r->in.message->string ) {
580 chkmsg = talloc_alpha_strcpy(p->mem_ctx,
581 r->in.message->string,
582 NULL);
583 if (chkmsg == NULL) {
584 return WERR_NOT_ENOUGH_MEMORY;
588 fstr_sprintf(str_timeout, "%d", r->in.timeout);
589 fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
590 fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
591 fstr_sprintf(str_reason, "%d", r->in.reason );
593 shutdown_script = talloc_all_string_sub(p->mem_ctx,
594 shutdown_script, "%z", chkmsg ? chkmsg : "");
595 if (!shutdown_script) {
596 return WERR_NOT_ENOUGH_MEMORY;
598 shutdown_script = talloc_all_string_sub(p->mem_ctx,
599 shutdown_script, "%t", str_timeout);
600 if (!shutdown_script) {
601 return WERR_NOT_ENOUGH_MEMORY;
603 shutdown_script = talloc_all_string_sub(p->mem_ctx,
604 shutdown_script, "%r", do_reboot);
605 if (!shutdown_script) {
606 return WERR_NOT_ENOUGH_MEMORY;
608 shutdown_script = talloc_all_string_sub(p->mem_ctx,
609 shutdown_script, "%f", f);
610 if (!shutdown_script) {
611 return WERR_NOT_ENOUGH_MEMORY;
613 shutdown_script = talloc_all_string_sub(p->mem_ctx,
614 shutdown_script, "%x", str_reason);
615 if (!shutdown_script) {
616 return WERR_NOT_ENOUGH_MEMORY;
619 can_shutdown = security_token_has_privilege(
620 session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
622 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
623 Take the error return from the script and provide it as the Windows return code. */
625 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
627 if ( can_shutdown )
628 become_root();
630 ret = smbrun(shutdown_script, NULL, NULL);
632 if ( can_shutdown )
633 unbecome_root();
635 /********** END SeRemoteShutdownPrivilege BLOCK **********/
637 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
638 shutdown_script, ret));
640 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
643 /*******************************************************************
644 _winreg_AbortSystemShutdown
645 ********************************************************************/
647 WERROR _winreg_AbortSystemShutdown(struct pipes_struct *p,
648 struct winreg_AbortSystemShutdown *r)
650 struct dcesrv_call_state *dce_call = p->dce_call;
651 struct auth_session_info *session_info =
652 dcesrv_call_session_info(dce_call);
653 const char *abort_shutdown_script = NULL;
654 const struct loadparm_substitution *lp_sub =
655 loadparm_s3_global_substitution();
656 int ret = -1;
657 bool can_shutdown = false;
659 abort_shutdown_script = lp_abort_shutdown_script(talloc_tos(), lp_sub);
660 if (!*abort_shutdown_script)
661 return WERR_ACCESS_DENIED;
663 can_shutdown = security_token_has_privilege(
664 session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
666 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
668 if ( can_shutdown )
669 become_root();
671 ret = smbrun(abort_shutdown_script, NULL, NULL);
673 if ( can_shutdown )
674 unbecome_root();
676 /********** END SeRemoteShutdownPrivilege BLOCK **********/
678 DEBUG(3,("_winreg_AbortSystemShutdown: Running the command `%s' gave %d\n",
679 abort_shutdown_script, ret));
681 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
684 /*******************************************************************
685 _winreg_RestoreKey
686 ********************************************************************/
688 WERROR _winreg_RestoreKey(struct pipes_struct *p,
689 struct winreg_RestoreKey *r)
691 struct registry_key *regkey = find_regkey_by_hnd(p,
692 r->in.handle,
693 HTYPE_REGKEY);
695 if ( !regkey ) {
696 return WERR_INVALID_HANDLE;
698 return WERR_BAD_PATHNAME;
701 /*******************************************************************
702 _winreg_SaveKey
703 ********************************************************************/
705 WERROR _winreg_SaveKey(struct pipes_struct *p,
706 struct winreg_SaveKey *r)
708 struct registry_key *regkey = find_regkey_by_hnd(p,
709 r->in.handle,
710 HTYPE_REGKEY);
712 if ( !regkey ) {
713 return WERR_INVALID_HANDLE;
715 return WERR_BAD_PATHNAME;
718 /*******************************************************************
719 _winreg_SaveKeyEx
720 ********************************************************************/
722 WERROR _winreg_SaveKeyEx(struct pipes_struct *p,
723 struct winreg_SaveKeyEx *r)
725 /* fill in your code here if you think this call should
726 do anything */
728 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
729 return WERR_NOT_SUPPORTED;
732 /*******************************************************************
733 _winreg_CreateKey
734 ********************************************************************/
736 WERROR _winreg_CreateKey(struct pipes_struct *p,
737 struct winreg_CreateKey *r)
739 struct registry_key *parent = find_regkey_by_hnd(p,
740 r->in.handle,
741 HTYPE_REGKEY);
742 struct registry_key *new_key = NULL;
743 WERROR result = WERR_OK;
745 if ( !parent )
746 return WERR_INVALID_HANDLE;
748 DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
749 "subkey name '%s'\n", parent->key->name, r->in.name.name));
751 result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
752 &new_key, r->out.action_taken);
753 if (!W_ERROR_IS_OK(result)) {
754 return result;
757 if (!create_policy_hnd(p, r->out.new_handle, HTYPE_REGKEY, new_key)) {
758 TALLOC_FREE(new_key);
759 return WERR_FILE_NOT_FOUND;
762 return WERR_OK;
765 /*******************************************************************
766 _winreg_SetValue
767 ********************************************************************/
769 WERROR _winreg_SetValue(struct pipes_struct *p,
770 struct winreg_SetValue *r)
772 struct registry_key *key = find_regkey_by_hnd(p,
773 r->in.handle,
774 HTYPE_REGKEY);
775 struct registry_value *val = NULL;
777 if ( !key )
778 return WERR_INVALID_HANDLE;
780 DEBUG(8,("_winreg_SetValue: Setting value for [%s:%s]\n",
781 key->key->name, r->in.name.name));
783 val = talloc_zero(p->mem_ctx, struct registry_value);
784 if (val == NULL) {
785 return WERR_NOT_ENOUGH_MEMORY;
788 val->type = r->in.type;
789 val->data = data_blob_talloc(p->mem_ctx, r->in.data, r->in.size);
791 return reg_setvalue(key, r->in.name.name, val);
794 /*******************************************************************
795 _winreg_DeleteKey
796 ********************************************************************/
798 WERROR _winreg_DeleteKey(struct pipes_struct *p,
799 struct winreg_DeleteKey *r)
801 struct registry_key *parent = find_regkey_by_hnd(p,
802 r->in.handle,
803 HTYPE_REGKEY);
805 if ( !parent )
806 return WERR_INVALID_HANDLE;
808 return reg_deletekey(parent, r->in.key.name);
812 /*******************************************************************
813 _winreg_DeleteValue
814 ********************************************************************/
816 WERROR _winreg_DeleteValue(struct pipes_struct *p,
817 struct winreg_DeleteValue *r)
819 struct registry_key *key = find_regkey_by_hnd(p,
820 r->in.handle,
821 HTYPE_REGKEY);
823 if ( !key )
824 return WERR_INVALID_HANDLE;
826 return reg_deletevalue(key, r->in.value.name);
829 /*******************************************************************
830 _winreg_GetKeySecurity
831 ********************************************************************/
833 WERROR _winreg_GetKeySecurity(struct pipes_struct *p,
834 struct winreg_GetKeySecurity *r)
836 struct registry_key *key = find_regkey_by_hnd(p,
837 r->in.handle,
838 HTYPE_REGKEY);
839 WERROR err = WERR_OK;
840 struct security_descriptor *secdesc = NULL;
841 uint8_t *data = NULL;
842 size_t len = 0;
844 if ( !key )
845 return WERR_INVALID_HANDLE;
847 /* access checks first */
849 if ( !(key->key->access_granted & SEC_STD_READ_CONTROL) )
850 return WERR_ACCESS_DENIED;
852 err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
853 if (!W_ERROR_IS_OK(err)) {
854 return err;
857 err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
858 &data, &len));
859 if (!W_ERROR_IS_OK(err)) {
860 return err;
863 if (len > r->out.sd->size) {
864 r->out.sd->size = len;
865 return WERR_INSUFFICIENT_BUFFER;
868 r->out.sd->size = len;
869 r->out.sd->len = len;
870 r->out.sd->data = data;
872 return WERR_OK;
875 /*******************************************************************
876 _winreg_SetKeySecurity
877 ********************************************************************/
879 WERROR _winreg_SetKeySecurity(struct pipes_struct *p,
880 struct winreg_SetKeySecurity *r)
882 struct registry_key *key = find_regkey_by_hnd(p,
883 r->in.handle,
884 HTYPE_REGKEY);
885 struct security_descriptor *secdesc = NULL;
886 WERROR err = WERR_OK;
888 if ( !key )
889 return WERR_INVALID_HANDLE;
891 /* access checks first */
893 if ( !(key->key->access_granted & SEC_STD_WRITE_DAC) )
894 return WERR_ACCESS_DENIED;
896 err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
897 r->in.sd->len, &secdesc));
898 if (!W_ERROR_IS_OK(err)) {
899 return err;
902 return reg_setkeysecurity(key, secdesc);
905 /*******************************************************************
906 _winreg_FlushKey
907 ********************************************************************/
909 WERROR _winreg_FlushKey(struct pipes_struct *p,
910 struct winreg_FlushKey *r)
912 /* I'm just replying OK because there's not a lot
913 here I see to do i --jerry */
915 return WERR_OK;
918 /*******************************************************************
919 _winreg_UnLoadKey
920 ********************************************************************/
922 WERROR _winreg_UnLoadKey(struct pipes_struct *p,
923 struct winreg_UnLoadKey *r)
925 /* fill in your code here if you think this call should
926 do anything */
928 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
929 return WERR_NOT_SUPPORTED;
932 /*******************************************************************
933 _winreg_ReplaceKey
934 ********************************************************************/
936 WERROR _winreg_ReplaceKey(struct pipes_struct *p,
937 struct winreg_ReplaceKey *r)
939 /* fill in your code here if you think this call should
940 do anything */
942 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
943 return WERR_NOT_SUPPORTED;
946 /*******************************************************************
947 _winreg_LoadKey
948 ********************************************************************/
950 WERROR _winreg_LoadKey(struct pipes_struct *p,
951 struct winreg_LoadKey *r)
953 /* fill in your code here if you think this call should
954 do anything */
956 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
957 return WERR_NOT_SUPPORTED;
960 /*******************************************************************
961 _winreg_NotifyChangeKeyValue
962 ********************************************************************/
964 WERROR _winreg_NotifyChangeKeyValue(struct pipes_struct *p,
965 struct winreg_NotifyChangeKeyValue *r)
967 return WERR_NOT_SUPPORTED;
970 /*******************************************************************
971 _winreg_QueryMultipleValues
972 ********************************************************************/
974 WERROR _winreg_QueryMultipleValues(struct pipes_struct *p,
975 struct winreg_QueryMultipleValues *r)
977 struct winreg_QueryMultipleValues2 r2;
978 uint32_t needed = 0;
980 r2.in.key_handle = r->in.key_handle;
981 r2.in.values_in = r->in.values_in;
982 r2.in.num_values = r->in.num_values;
983 r2.in.offered = r->in.buffer_size;
984 r2.in.buffer = r->in.buffer;
985 r2.out.values_out = r->out.values_out;
986 r2.out.needed = &needed;
987 r2.out.buffer = r->out.buffer;
989 return _winreg_QueryMultipleValues2(p, &r2);
992 /*******************************************************************
993 ********************************************************************/
995 static WERROR construct_multiple_entry(TALLOC_CTX *mem_ctx,
996 const char *valuename,
997 uint32_t value_length,
998 uint32_t offset,
999 enum winreg_Type type,
1000 struct QueryMultipleValue *r)
1002 r->ve_valuename = talloc_zero(mem_ctx, struct winreg_ValNameBuf);
1003 if (r->ve_valuename == NULL) {
1004 return WERR_NOT_ENOUGH_MEMORY;
1007 r->ve_valuename->name = talloc_strdup(r->ve_valuename, valuename ? valuename : "");
1008 if (r->ve_valuename->name == NULL) {
1009 return WERR_NOT_ENOUGH_MEMORY;
1012 r->ve_valuename->size = strlen_m_term(r->ve_valuename->name)*2;
1013 r->ve_valuelen = value_length;
1014 r->ve_valueptr = offset;
1015 r->ve_type = type;
1017 return WERR_OK;
1020 /*******************************************************************
1021 _winreg_QueryMultipleValues2
1022 ********************************************************************/
1024 WERROR _winreg_QueryMultipleValues2(struct pipes_struct *p,
1025 struct winreg_QueryMultipleValues2 *r)
1027 struct registry_key *regkey = find_regkey_by_hnd(p,
1028 r->in.key_handle,
1029 HTYPE_REGKEY);
1030 struct registry_value *vals = NULL;
1031 const char **names = NULL;
1032 uint32_t offset = 0, num_vals = 0;
1033 DATA_BLOB result = data_blob_null;
1034 uint32_t i = 0;
1035 WERROR err = WERR_OK;
1037 if (!regkey) {
1038 return WERR_INVALID_HANDLE;
1041 names = talloc_zero_array(p->mem_ctx, const char *, r->in.num_values);
1042 if (names == NULL) {
1043 return WERR_NOT_ENOUGH_MEMORY;
1046 for (i=0; i < r->in.num_values; i++) {
1047 if (r->in.values_in[i].ve_valuename &&
1048 r->in.values_in[i].ve_valuename->name) {
1049 names[i] = talloc_strdup(names,
1050 r->in.values_in[i].ve_valuename->name);
1051 if (names[i] == NULL) {
1052 return WERR_NOT_ENOUGH_MEMORY;
1057 err = reg_querymultiplevalues(p->mem_ctx, regkey,
1058 r->in.num_values, names,
1059 &num_vals, &vals);
1060 if (!W_ERROR_IS_OK(err)) {
1061 return err;
1064 result = data_blob_talloc(p->mem_ctx, NULL, 0);
1066 for (i=0; i < r->in.num_values; i++) {
1067 const char *valuename = NULL;
1069 if (vals[i].data.length > 0) {
1070 if (!data_blob_append(p->mem_ctx, &result,
1071 vals[i].data.data,
1072 vals[i].data.length)) {
1073 return WERR_NOT_ENOUGH_MEMORY;
1077 if (r->in.values_in[i].ve_valuename &&
1078 r->in.values_in[i].ve_valuename->name) {
1079 valuename = r->in.values_in[i].ve_valuename->name;
1082 err = construct_multiple_entry(r->out.values_out,
1083 valuename,
1084 vals[i].data.length,
1085 offset,
1086 vals[i].type,
1087 &r->out.values_out[i]);
1088 if (!W_ERROR_IS_OK(err)) {
1089 return err;
1092 offset += vals[i].data.length;
1095 *r->out.needed = result.length;
1097 if (r->in.num_values != num_vals) {
1098 return WERR_FILE_NOT_FOUND;
1101 if (*r->in.offered >= *r->out.needed) {
1102 if (r->out.buffer) {
1103 memcpy(r->out.buffer, result.data, MIN(result.length, *r->in.offered));
1105 return WERR_OK;
1106 } else {
1107 return WERR_MORE_DATA;
1111 /*******************************************************************
1112 _winreg_DeleteKeyEx
1113 ********************************************************************/
1115 WERROR _winreg_DeleteKeyEx(struct pipes_struct *p,
1116 struct winreg_DeleteKeyEx *r)
1118 /* fill in your code here if you think this call should
1119 do anything */
1121 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1122 return WERR_NOT_SUPPORTED;
1125 /* include the generated boilerplate */
1126 #include "librpc/gen_ndr/ndr_winreg_scompat.c"