s3: Lift the server_messaging_context from send_spoolss_notify2_msg
[Samba/gbeck.git] / source3 / rpc_server / srv_winreg_nt.c
blobb4105a026b545aaa7c65b12d0619127dfe4cfeb0
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 "../librpc/gen_ndr/srv_winreg.h"
25 #include "registry/reg_parse_prs.h"
26 #include "registry.h"
27 #include "registry/reg_perfcount.h"
29 #undef DBGC_CLASS
30 #define DBGC_CLASS DBGC_RPC_SRV
32 /******************************************************************
33 Find a registry key handle and return a struct registry_key *
34 *****************************************************************/
36 static struct registry_key *find_regkey_by_hnd(struct pipes_struct *p,
37 struct policy_handle *hnd)
39 struct registry_key *regkey = NULL;
41 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) {
42 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
43 return NULL;
46 return regkey;
49 /*******************************************************************
50 Function for open a new registry handle and creating a handle
51 Note that P should be valid & hnd should already have space
53 When we open a key, we store the full path to the key as
54 HK[LM|U]\<key>\<key>\...
55 *******************************************************************/
57 static WERROR open_registry_key(struct pipes_struct *p,
58 struct policy_handle *hnd,
59 struct registry_key *parent,
60 const char *subkeyname,
61 uint32_t access_desired)
63 WERROR result = WERR_OK;
64 struct registry_key *key;
66 if (parent == NULL) {
67 result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
68 p->server_info->ptok, &key);
70 else {
71 result = reg_openkey(p->mem_ctx, parent, subkeyname,
72 access_desired, &key);
75 if ( !W_ERROR_IS_OK(result) ) {
76 return result;
79 if ( !create_policy_hnd( p, hnd, key ) ) {
80 return WERR_BADFILE;
83 return WERR_OK;
86 /*******************************************************************
87 Function for open a new registry handle and creating a handle
88 Note that P should be valid & hnd should already have space
89 *******************************************************************/
91 static bool close_registry_key(struct pipes_struct *p,
92 struct policy_handle *hnd)
94 struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
96 if ( !regkey ) {
97 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
98 OUR_HANDLE(hnd)));
99 return False;
102 close_policy_hnd(p, hnd);
104 return True;
107 /********************************************************************
108 _winreg_CloseKey
109 ********************************************************************/
111 WERROR _winreg_CloseKey(struct pipes_struct *p,
112 struct winreg_CloseKey *r)
114 /* close the policy handle */
116 if (!close_registry_key(p, r->in.handle))
117 return WERR_BADFID;
119 ZERO_STRUCTP(r->out.handle);
121 return WERR_OK;
124 /*******************************************************************
125 _winreg_OpenHKLM
126 ********************************************************************/
128 WERROR _winreg_OpenHKLM(struct pipes_struct *p,
129 struct winreg_OpenHKLM *r)
131 return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
134 /*******************************************************************
135 _winreg_OpenHKPD
136 ********************************************************************/
138 WERROR _winreg_OpenHKPD(struct pipes_struct *p,
139 struct winreg_OpenHKPD *r)
141 return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
144 /*******************************************************************
145 _winreg_OpenHKPT
146 ********************************************************************/
148 WERROR _winreg_OpenHKPT(struct pipes_struct *p,
149 struct winreg_OpenHKPT *r)
151 return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
154 /*******************************************************************
155 _winreg_OpenHKCR
156 ********************************************************************/
158 WERROR _winreg_OpenHKCR(struct pipes_struct *p,
159 struct winreg_OpenHKCR *r)
161 return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
164 /*******************************************************************
165 _winreg_OpenHKU
166 ********************************************************************/
168 WERROR _winreg_OpenHKU(struct pipes_struct *p,
169 struct winreg_OpenHKU *r)
171 return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
174 /*******************************************************************
175 _winreg_OpenHKCU
176 ********************************************************************/
178 WERROR _winreg_OpenHKCU(struct pipes_struct *p,
179 struct winreg_OpenHKCU *r)
181 return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
184 /*******************************************************************
185 _winreg_OpenHKCC
186 ********************************************************************/
188 WERROR _winreg_OpenHKCC(struct pipes_struct *p,
189 struct winreg_OpenHKCC *r)
191 return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
194 /*******************************************************************
195 _winreg_OpenHKDD
196 ********************************************************************/
198 WERROR _winreg_OpenHKDD(struct pipes_struct *p,
199 struct winreg_OpenHKDD *r)
201 return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
204 /*******************************************************************
205 _winreg_OpenHKPN
206 ********************************************************************/
208 WERROR _winreg_OpenHKPN(struct pipes_struct *p,
209 struct winreg_OpenHKPN *r)
211 return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
214 /*******************************************************************
215 _winreg_OpenKey
216 ********************************************************************/
218 WERROR _winreg_OpenKey(struct pipes_struct *p,
219 struct winreg_OpenKey *r)
221 struct registry_key *parent = find_regkey_by_hnd(p, r->in.parent_handle );
223 if ( !parent )
224 return WERR_BADFID;
226 return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
229 /*******************************************************************
230 _winreg_QueryValue
231 ********************************************************************/
233 WERROR _winreg_QueryValue(struct pipes_struct *p,
234 struct winreg_QueryValue *r)
236 WERROR status = WERR_BADFILE;
237 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
238 prs_struct prs_hkpd;
240 uint8_t *outbuf;
241 uint32_t outbuf_size;
243 bool free_buf = False;
244 bool free_prs = False;
246 if ( !regkey )
247 return WERR_BADFID;
249 if (r->in.value_name->name == NULL) {
250 return WERR_INVALID_PARAM;
253 if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
254 return WERR_INVALID_PARAM;
257 DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
258 DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
260 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
261 if(regkey->key->type == REG_KEY_HKPD)
263 if (strequal(r->in.value_name->name, "Global")) {
264 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
265 return WERR_NOMEM;
266 status = reg_perfcount_get_hkpd(
267 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
268 outbuf = (uint8_t *)prs_hkpd.data_p;
269 free_prs = True;
271 else if (strequal(r->in.value_name->name, "Counter 009")) {
272 outbuf_size = reg_perfcount_get_counter_names(
273 reg_perfcount_get_base_index(),
274 (char **)(void *)&outbuf);
275 free_buf = True;
277 else if (strequal(r->in.value_name->name, "Explain 009")) {
278 outbuf_size = reg_perfcount_get_counter_help(
279 reg_perfcount_get_base_index(),
280 (char **)(void *)&outbuf);
281 free_buf = True;
283 else if (isdigit(r->in.value_name->name[0])) {
284 /* we probably have a request for a specific object
285 * here */
286 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
287 return WERR_NOMEM;
288 status = reg_perfcount_get_hkpd(
289 &prs_hkpd, *r->in.data_size, &outbuf_size,
290 r->in.value_name->name);
291 outbuf = (uint8_t *)prs_hkpd.data_p;
292 free_prs = True;
294 else {
295 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
296 r->in.value_name->name));
297 return WERR_BADFILE;
300 *r->out.type = REG_BINARY;
302 else {
303 struct registry_value *val;
305 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
306 &val);
307 if (!W_ERROR_IS_OK(status)) {
309 DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
310 win_errstr(status)));
312 if (r->out.data_size) {
313 *r->out.data_size = 0;
315 if (r->out.data_length) {
316 *r->out.data_length = 0;
318 return status;
321 outbuf = val->data.data;
322 outbuf_size = val->data.length;
323 *r->out.type = val->type;
326 status = WERR_BADFILE;
328 if (*r->in.data_size < outbuf_size) {
329 *r->out.data_size = outbuf_size;
330 status = r->in.data ? WERR_MORE_DATA : WERR_OK;
331 } else {
332 *r->out.data_length = outbuf_size;
333 *r->out.data_size = outbuf_size;
334 if (r->out.data) {
335 memcpy(r->out.data, outbuf, outbuf_size);
337 status = WERR_OK;
340 if (free_prs) prs_mem_free(&prs_hkpd);
341 if (free_buf) SAFE_FREE(outbuf);
343 return status;
346 /*****************************************************************************
347 _winreg_QueryInfoKey
348 ****************************************************************************/
350 WERROR _winreg_QueryInfoKey(struct pipes_struct *p,
351 struct winreg_QueryInfoKey *r)
353 WERROR status = WERR_OK;
354 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
356 if ( !regkey )
357 return WERR_BADFID;
359 r->out.classname->name = NULL;
361 status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
362 r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
363 r->out.max_valbufsize, r->out.secdescsize,
364 r->out.last_changed_time);
365 if (!W_ERROR_IS_OK(status)) {
366 return status;
370 * These calculations account for the registry buffers being
371 * UTF-16. They are inexact at best, but so far they worked.
374 *r->out.max_subkeylen *= 2;
376 *r->out.max_valnamelen += 1;
377 *r->out.max_valnamelen *= 2;
379 return WERR_OK;
383 /*****************************************************************************
384 _winreg_GetVersion
385 ****************************************************************************/
387 WERROR _winreg_GetVersion(struct pipes_struct *p,
388 struct winreg_GetVersion *r)
390 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
392 if ( !regkey )
393 return WERR_BADFID;
395 return reg_getversion(r->out.version);
399 /*****************************************************************************
400 _winreg_EnumKey
401 ****************************************************************************/
403 WERROR _winreg_EnumKey(struct pipes_struct *p,
404 struct winreg_EnumKey *r)
406 WERROR err;
407 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
409 if ( !key )
410 return WERR_BADFID;
412 if ( !r->in.name || !r->in.keyclass )
413 return WERR_INVALID_PARAM;
415 DEBUG(8,("_winreg_EnumKey: enumerating key [%s]\n", key->key->name));
417 err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, (char **)&r->out.name->name,
418 r->out.last_changed_time);
419 if (!W_ERROR_IS_OK(err)) {
420 return err;
422 r->out.keyclass->name = "";
423 return WERR_OK;
426 /*****************************************************************************
427 _winreg_EnumValue
428 ****************************************************************************/
430 WERROR _winreg_EnumValue(struct pipes_struct *p,
431 struct winreg_EnumValue *r)
433 WERROR err;
434 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
435 char *valname;
436 struct registry_value *val;
438 if ( !key )
439 return WERR_BADFID;
441 if ( !r->in.name )
442 return WERR_INVALID_PARAM;
444 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
445 key->key->name));
447 err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
448 if (!W_ERROR_IS_OK(err)) {
449 return err;
452 if (r->out.name != NULL) {
453 r->out.name->name = valname;
456 if (r->out.type != NULL) {
457 *r->out.type = val->type;
460 if (r->out.value != NULL) {
461 if ((r->out.size == NULL) || (r->out.length == NULL)) {
462 return WERR_INVALID_PARAM;
465 if (val->data.length > *r->out.size) {
466 return WERR_MORE_DATA;
469 memcpy( r->out.value, val->data.data, val->data.length );
472 if (r->out.length != NULL) {
473 *r->out.length = val->data.length;
475 if (r->out.size != NULL) {
476 *r->out.size = val->data.length;
479 return WERR_OK;
482 /*******************************************************************
483 _winreg_InitiateSystemShutdown
484 ********************************************************************/
486 WERROR _winreg_InitiateSystemShutdown(struct pipes_struct *p,
487 struct winreg_InitiateSystemShutdown *r)
489 struct winreg_InitiateSystemShutdownEx s;
491 s.in.hostname = r->in.hostname;
492 s.in.message = r->in.message;
493 s.in.timeout = r->in.timeout;
494 s.in.force_apps = r->in.force_apps;
495 s.in.do_reboot = r->in.do_reboot;
496 s.in.reason = 0;
498 /* thunk down to _winreg_InitiateSystemShutdownEx()
499 (just returns a status) */
501 return _winreg_InitiateSystemShutdownEx( p, &s );
504 /*******************************************************************
505 _winreg_InitiateSystemShutdownEx
506 ********************************************************************/
508 #define SHUTDOWN_R_STRING "-r"
509 #define SHUTDOWN_F_STRING "-f"
512 WERROR _winreg_InitiateSystemShutdownEx(struct pipes_struct *p,
513 struct winreg_InitiateSystemShutdownEx *r)
515 char *shutdown_script = NULL;
516 char *msg = NULL;
517 char *chkmsg = NULL;
518 fstring str_timeout;
519 fstring str_reason;
520 fstring do_reboot;
521 fstring f;
522 int ret;
523 bool can_shutdown;
525 shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
526 if (!shutdown_script) {
527 return WERR_NOMEM;
529 if (!*shutdown_script) {
530 return WERR_ACCESS_DENIED;
533 /* pull the message string and perform necessary sanity checks on it */
535 if ( r->in.message && r->in.message->string ) {
536 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
537 return WERR_NOMEM;
539 chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
540 if (!chkmsg) {
541 return WERR_NOMEM;
543 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
546 fstr_sprintf(str_timeout, "%d", r->in.timeout);
547 fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
548 fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
549 fstr_sprintf(str_reason, "%d", r->in.reason );
551 shutdown_script = talloc_all_string_sub(p->mem_ctx,
552 shutdown_script, "%z", chkmsg ? chkmsg : "");
553 if (!shutdown_script) {
554 return WERR_NOMEM;
556 shutdown_script = talloc_all_string_sub(p->mem_ctx,
557 shutdown_script, "%t", str_timeout);
558 if (!shutdown_script) {
559 return WERR_NOMEM;
561 shutdown_script = talloc_all_string_sub(p->mem_ctx,
562 shutdown_script, "%r", do_reboot);
563 if (!shutdown_script) {
564 return WERR_NOMEM;
566 shutdown_script = talloc_all_string_sub(p->mem_ctx,
567 shutdown_script, "%f", f);
568 if (!shutdown_script) {
569 return WERR_NOMEM;
571 shutdown_script = talloc_all_string_sub(p->mem_ctx,
572 shutdown_script, "%x", str_reason);
573 if (!shutdown_script) {
574 return WERR_NOMEM;
577 can_shutdown = user_has_privileges( p->server_info->ptok,
578 &se_remote_shutdown );
580 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
581 Take the error return from the script and provide it as the Windows return code. */
583 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
585 if ( can_shutdown )
586 become_root();
588 ret = smbrun( shutdown_script, NULL );
590 if ( can_shutdown )
591 unbecome_root();
593 /********** END SeRemoteShutdownPrivilege BLOCK **********/
595 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
596 shutdown_script, ret));
598 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
601 /*******************************************************************
602 _winreg_AbortSystemShutdown
603 ********************************************************************/
605 WERROR _winreg_AbortSystemShutdown(struct pipes_struct *p,
606 struct winreg_AbortSystemShutdown *r)
608 const char *abort_shutdown_script;
609 int ret;
610 bool can_shutdown;
612 abort_shutdown_script = lp_abort_shutdown_script();
614 if (!*abort_shutdown_script)
615 return WERR_ACCESS_DENIED;
617 can_shutdown = user_has_privileges( p->server_info->ptok,
618 &se_remote_shutdown );
620 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
622 if ( can_shutdown )
623 become_root();
625 ret = smbrun( abort_shutdown_script, NULL );
627 if ( can_shutdown )
628 unbecome_root();
630 /********** END SeRemoteShutdownPrivilege BLOCK **********/
632 DEBUG(3,("_winreg_AbortSystemShutdown: Running the command `%s' gave %d\n",
633 abort_shutdown_script, ret));
635 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
638 /*******************************************************************
639 ********************************************************************/
641 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
643 char *p = NULL;
644 int num_services = lp_numservices();
645 int snum = -1;
646 const char *share_path;
647 char *fname = *pp_fname;
649 /* convert to a unix path, stripping the C:\ along the way */
651 if (!(p = valid_share_pathname(ctx, fname))) {
652 return -1;
655 /* has to exist within a valid file share */
657 for (snum=0; snum<num_services; snum++) {
658 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
659 continue;
662 share_path = lp_pathname(snum);
664 /* make sure we have a path (e.g. [homes] ) */
665 if (strlen(share_path) == 0) {
666 continue;
669 if (strncmp(share_path, p, strlen(share_path)) == 0) {
670 break;
674 *pp_fname = p;
675 return (snum < num_services) ? snum : -1;
678 /*******************************************************************
679 _winreg_RestoreKey
680 ********************************************************************/
682 WERROR _winreg_RestoreKey(struct pipes_struct *p,
683 struct winreg_RestoreKey *r)
685 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
686 char *fname = NULL;
687 int snum;
689 if ( !regkey )
690 return WERR_BADFID;
692 if ( !r->in.filename || !r->in.filename->name )
693 return WERR_INVALID_PARAM;
695 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
696 if (!fname) {
697 return WERR_NOMEM;
700 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
701 "\"%s\"\n", regkey->key->name, fname));
703 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
704 return WERR_OBJECT_PATH_INVALID;
706 /* user must posses SeRestorePrivilege for this this proceed */
708 if ( !user_has_privileges( p->server_info->ptok, &se_restore ) )
709 return WERR_ACCESS_DENIED;
711 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
712 regkey->key->name, fname, lp_servicename(snum) ));
714 return reg_restorekey(regkey, fname);
717 /*******************************************************************
718 _winreg_SaveKey
719 ********************************************************************/
721 WERROR _winreg_SaveKey(struct pipes_struct *p,
722 struct winreg_SaveKey *r)
724 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
725 char *fname = NULL;
726 int snum = -1;
728 if ( !regkey )
729 return WERR_BADFID;
731 if ( !r->in.filename || !r->in.filename->name )
732 return WERR_INVALID_PARAM;
734 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
735 if (!fname) {
736 return WERR_NOMEM;
739 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
740 regkey->key->name, fname));
742 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
743 return WERR_OBJECT_PATH_INVALID;
745 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
746 regkey->key->name, fname, lp_servicename(snum) ));
748 return reg_savekey(regkey, fname);
751 /*******************************************************************
752 _winreg_SaveKeyEx
753 ********************************************************************/
755 WERROR _winreg_SaveKeyEx(struct pipes_struct *p,
756 struct winreg_SaveKeyEx *r)
758 /* fill in your code here if you think this call should
759 do anything */
761 p->rng_fault_state = True;
762 return WERR_NOT_SUPPORTED;
765 /*******************************************************************
766 _winreg_CreateKey
767 ********************************************************************/
769 WERROR _winreg_CreateKey(struct pipes_struct *p,
770 struct winreg_CreateKey *r)
772 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
773 struct registry_key *new_key;
774 WERROR result;
776 if ( !parent )
777 return WERR_BADFID;
779 DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
780 "subkey name '%s'\n", parent->key->name, r->in.name.name));
782 result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
783 &new_key, r->out.action_taken);
784 if (!W_ERROR_IS_OK(result)) {
785 return result;
788 if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
789 TALLOC_FREE(new_key);
790 return WERR_BADFILE;
793 return WERR_OK;
796 /*******************************************************************
797 _winreg_SetValue
798 ********************************************************************/
800 WERROR _winreg_SetValue(struct pipes_struct *p,
801 struct winreg_SetValue *r)
803 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
804 struct registry_value *val;
806 if ( !key )
807 return WERR_BADFID;
809 DEBUG(8,("_winreg_SetValue: Setting value for [%s:%s]\n",
810 key->key->name, r->in.name.name));
812 val = talloc_zero(p->mem_ctx, struct registry_value);
813 if (val == NULL) {
814 return WERR_NOMEM;
817 val->type = r->in.type;
818 val->data = data_blob_talloc(p->mem_ctx, r->in.data, r->in.size);
820 return reg_setvalue(key, r->in.name.name, val);
823 /*******************************************************************
824 _winreg_DeleteKey
825 ********************************************************************/
827 WERROR _winreg_DeleteKey(struct pipes_struct *p,
828 struct winreg_DeleteKey *r)
830 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
832 if ( !parent )
833 return WERR_BADFID;
835 return reg_deletekey(parent, r->in.key.name);
839 /*******************************************************************
840 _winreg_DeleteValue
841 ********************************************************************/
843 WERROR _winreg_DeleteValue(struct pipes_struct *p,
844 struct winreg_DeleteValue *r)
846 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
848 if ( !key )
849 return WERR_BADFID;
851 return reg_deletevalue(key, r->in.value.name);
854 /*******************************************************************
855 _winreg_GetKeySecurity
856 ********************************************************************/
858 WERROR _winreg_GetKeySecurity(struct pipes_struct *p,
859 struct winreg_GetKeySecurity *r)
861 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
862 WERROR err;
863 struct security_descriptor *secdesc;
864 uint8 *data;
865 size_t len;
867 if ( !key )
868 return WERR_BADFID;
870 /* access checks first */
872 if ( !(key->key->access_granted & SEC_STD_READ_CONTROL) )
873 return WERR_ACCESS_DENIED;
875 err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
876 if (!W_ERROR_IS_OK(err)) {
877 return err;
880 err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
881 &data, &len));
882 if (!W_ERROR_IS_OK(err)) {
883 return err;
886 if (len > r->out.sd->size) {
887 r->out.sd->size = len;
888 return WERR_INSUFFICIENT_BUFFER;
891 r->out.sd->size = len;
892 r->out.sd->len = len;
893 r->out.sd->data = data;
895 return WERR_OK;
898 /*******************************************************************
899 _winreg_SetKeySecurity
900 ********************************************************************/
902 WERROR _winreg_SetKeySecurity(struct pipes_struct *p,
903 struct winreg_SetKeySecurity *r)
905 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
906 struct security_descriptor *secdesc;
907 WERROR err;
909 if ( !key )
910 return WERR_BADFID;
912 /* access checks first */
914 if ( !(key->key->access_granted & SEC_STD_WRITE_DAC) )
915 return WERR_ACCESS_DENIED;
917 err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
918 r->in.sd->len, &secdesc));
919 if (!W_ERROR_IS_OK(err)) {
920 return err;
923 return reg_setkeysecurity(key, secdesc);
926 /*******************************************************************
927 _winreg_FlushKey
928 ********************************************************************/
930 WERROR _winreg_FlushKey(struct pipes_struct *p,
931 struct winreg_FlushKey *r)
933 /* I'm just replying OK because there's not a lot
934 here I see to do i --jerry */
936 return WERR_OK;
939 /*******************************************************************
940 _winreg_UnLoadKey
941 ********************************************************************/
943 WERROR _winreg_UnLoadKey(struct pipes_struct *p,
944 struct winreg_UnLoadKey *r)
946 /* fill in your code here if you think this call should
947 do anything */
949 p->rng_fault_state = True;
950 return WERR_NOT_SUPPORTED;
953 /*******************************************************************
954 _winreg_ReplaceKey
955 ********************************************************************/
957 WERROR _winreg_ReplaceKey(struct pipes_struct *p,
958 struct winreg_ReplaceKey *r)
960 /* fill in your code here if you think this call should
961 do anything */
963 p->rng_fault_state = True;
964 return WERR_NOT_SUPPORTED;
967 /*******************************************************************
968 _winreg_LoadKey
969 ********************************************************************/
971 WERROR _winreg_LoadKey(struct pipes_struct *p,
972 struct winreg_LoadKey *r)
974 /* fill in your code here if you think this call should
975 do anything */
977 p->rng_fault_state = True;
978 return WERR_NOT_SUPPORTED;
981 /*******************************************************************
982 _winreg_NotifyChangeKeyValue
983 ********************************************************************/
985 WERROR _winreg_NotifyChangeKeyValue(struct pipes_struct *p,
986 struct winreg_NotifyChangeKeyValue *r)
988 return WERR_NOT_SUPPORTED;
991 /*******************************************************************
992 _winreg_QueryMultipleValues
993 ********************************************************************/
995 WERROR _winreg_QueryMultipleValues(struct pipes_struct *p,
996 struct winreg_QueryMultipleValues *r)
998 struct winreg_QueryMultipleValues2 r2;
999 uint32_t needed;
1001 r2.in.key_handle = r->in.key_handle;
1002 r2.in.values_in = r->in.values_in;
1003 r2.in.num_values = r->in.num_values;
1004 r2.in.offered = r->in.buffer_size;
1005 r2.in.buffer = r->in.buffer;
1006 r2.out.values_out = r->out.values_out;
1007 r2.out.needed = &needed;
1008 r2.out.buffer = r->out.buffer;
1010 return _winreg_QueryMultipleValues2(p, &r2);
1013 /*******************************************************************
1014 ********************************************************************/
1016 static WERROR construct_multiple_entry(TALLOC_CTX *mem_ctx,
1017 const char *valuename,
1018 uint32_t value_length,
1019 uint32_t offset,
1020 enum winreg_Type type,
1021 struct QueryMultipleValue *r)
1023 r->ve_valuename = talloc_zero(mem_ctx, struct winreg_ValNameBuf);
1024 if (r->ve_valuename == NULL) {
1025 return WERR_NOMEM;
1028 r->ve_valuename->name = talloc_strdup(r->ve_valuename, valuename ? valuename : "");
1029 if (r->ve_valuename->name == NULL) {
1030 return WERR_NOMEM;
1033 r->ve_valuename->size = strlen_m_term(r->ve_valuename->name)*2;
1034 r->ve_valuelen = value_length;
1035 r->ve_valueptr = offset;
1036 r->ve_type = type;
1038 return WERR_OK;
1041 /*******************************************************************
1042 _winreg_QueryMultipleValues2
1043 ********************************************************************/
1045 WERROR _winreg_QueryMultipleValues2(struct pipes_struct *p,
1046 struct winreg_QueryMultipleValues2 *r)
1048 struct registry_key *regkey = find_regkey_by_hnd(p, r->in.key_handle);
1049 struct registry_value *vals = NULL;
1050 const char **names = NULL;
1051 uint32_t offset = 0, num_vals = 0;
1052 DATA_BLOB result;
1053 int i;
1054 WERROR err;
1056 if (!regkey) {
1057 return WERR_BADFID;
1060 names = talloc_zero_array(p->mem_ctx, const char *, r->in.num_values);
1061 if (names == NULL) {
1062 return WERR_NOMEM;
1065 for (i=0; i < r->in.num_values; i++) {
1066 if (r->in.values_in[i].ve_valuename &&
1067 r->in.values_in[i].ve_valuename->name) {
1068 names[i] = talloc_strdup(names,
1069 r->in.values_in[i].ve_valuename->name);
1070 if (names[i] == NULL) {
1071 return WERR_NOMEM;
1076 err = reg_querymultiplevalues(p->mem_ctx, regkey,
1077 r->in.num_values, names,
1078 &num_vals, &vals);
1079 if (!W_ERROR_IS_OK(err)) {
1080 return err;
1083 result = data_blob_talloc(p->mem_ctx, NULL, 0);
1085 for (i=0; i < r->in.num_values; i++) {
1086 const char *valuename = NULL;
1088 if (vals[i].data.length > 0) {
1089 if (!data_blob_append(p->mem_ctx, &result,
1090 vals[i].data.data,
1091 vals[i].data.length)) {
1092 return WERR_NOMEM;
1096 if (r->in.values_in[i].ve_valuename &&
1097 r->in.values_in[i].ve_valuename->name) {
1098 valuename = r->in.values_in[i].ve_valuename->name;
1101 err = construct_multiple_entry(r->out.values_out,
1102 valuename,
1103 vals[i].data.length,
1104 offset,
1105 vals[i].type,
1106 &r->out.values_out[i]);
1107 if (!W_ERROR_IS_OK(err)) {
1108 return err;
1111 offset += vals[i].data.length;
1114 *r->out.needed = result.length;
1116 if (r->in.num_values != num_vals) {
1117 return WERR_BADFILE;
1120 if (*r->in.offered >= *r->out.needed) {
1121 if (r->out.buffer) {
1122 memcpy(r->out.buffer, result.data, MIN(result.length, *r->in.offered));
1124 return WERR_OK;
1125 } else {
1126 return WERR_MORE_DATA;
1130 /*******************************************************************
1131 _winreg_DeleteKeyEx
1132 ********************************************************************/
1134 WERROR _winreg_DeleteKeyEx(struct pipes_struct *p,
1135 struct winreg_DeleteKeyEx *r)
1137 /* fill in your code here if you think this call should
1138 do anything */
1140 p->rng_fault_state = True;
1141 return WERR_NOT_SUPPORTED;