s4-kdc: make DB_GLUE a private library
[Samba.git] / source3 / rpc_server / srv_winreg_nt.c
blob298f33ab705bae4fc98be1877b56ce5faa7d3d23
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_api.h"
28 #include "registry/reg_api_regf.h"
29 #include "registry/reg_perfcount.h"
30 #include "rpc_misc.h"
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
35 /******************************************************************
36 Find a registry key handle and return a struct registry_key *
37 *****************************************************************/
39 static struct registry_key *find_regkey_by_hnd(struct pipes_struct *p,
40 struct policy_handle *hnd)
42 struct registry_key *regkey = NULL;
44 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) {
45 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
46 return NULL;
49 return regkey;
52 /*******************************************************************
53 Function for open a new registry handle and creating a handle
54 Note that P should be valid & hnd should already have space
56 When we open a key, we store the full path to the key as
57 HK[LM|U]\<key>\<key>\...
58 *******************************************************************/
60 static WERROR open_registry_key(struct pipes_struct *p,
61 struct policy_handle *hnd,
62 struct registry_key *parent,
63 const char *subkeyname,
64 uint32_t access_desired)
66 WERROR result = WERR_OK;
67 struct registry_key *key;
69 if (parent == NULL) {
70 result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
71 p->server_info->ptok, &key);
73 else {
74 result = reg_openkey(p->mem_ctx, parent, subkeyname,
75 access_desired, &key);
78 if ( !W_ERROR_IS_OK(result) ) {
79 return result;
82 if ( !create_policy_hnd( p, hnd, key ) ) {
83 return WERR_BADFILE;
86 return WERR_OK;
89 /*******************************************************************
90 Function for open a new registry handle and creating a handle
91 Note that P should be valid & hnd should already have space
92 *******************************************************************/
94 static bool close_registry_key(struct pipes_struct *p,
95 struct policy_handle *hnd)
97 struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
99 if ( !regkey ) {
100 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
101 OUR_HANDLE(hnd)));
102 return False;
105 close_policy_hnd(p, hnd);
107 return True;
110 /********************************************************************
111 _winreg_CloseKey
112 ********************************************************************/
114 WERROR _winreg_CloseKey(struct pipes_struct *p,
115 struct winreg_CloseKey *r)
117 /* close the policy handle */
119 if (!close_registry_key(p, r->in.handle))
120 return WERR_BADFID;
122 ZERO_STRUCTP(r->out.handle);
124 return WERR_OK;
127 /*******************************************************************
128 _winreg_OpenHKLM
129 ********************************************************************/
131 WERROR _winreg_OpenHKLM(struct pipes_struct *p,
132 struct winreg_OpenHKLM *r)
134 return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
137 /*******************************************************************
138 _winreg_OpenHKPD
139 ********************************************************************/
141 WERROR _winreg_OpenHKPD(struct pipes_struct *p,
142 struct winreg_OpenHKPD *r)
144 return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
147 /*******************************************************************
148 _winreg_OpenHKPT
149 ********************************************************************/
151 WERROR _winreg_OpenHKPT(struct pipes_struct *p,
152 struct winreg_OpenHKPT *r)
154 return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
157 /*******************************************************************
158 _winreg_OpenHKCR
159 ********************************************************************/
161 WERROR _winreg_OpenHKCR(struct pipes_struct *p,
162 struct winreg_OpenHKCR *r)
164 return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
167 /*******************************************************************
168 _winreg_OpenHKU
169 ********************************************************************/
171 WERROR _winreg_OpenHKU(struct pipes_struct *p,
172 struct winreg_OpenHKU *r)
174 return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
177 /*******************************************************************
178 _winreg_OpenHKCU
179 ********************************************************************/
181 WERROR _winreg_OpenHKCU(struct pipes_struct *p,
182 struct winreg_OpenHKCU *r)
184 return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
187 /*******************************************************************
188 _winreg_OpenHKCC
189 ********************************************************************/
191 WERROR _winreg_OpenHKCC(struct pipes_struct *p,
192 struct winreg_OpenHKCC *r)
194 return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
197 /*******************************************************************
198 _winreg_OpenHKDD
199 ********************************************************************/
201 WERROR _winreg_OpenHKDD(struct pipes_struct *p,
202 struct winreg_OpenHKDD *r)
204 return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
207 /*******************************************************************
208 _winreg_OpenHKPN
209 ********************************************************************/
211 WERROR _winreg_OpenHKPN(struct pipes_struct *p,
212 struct winreg_OpenHKPN *r)
214 return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
217 /*******************************************************************
218 _winreg_OpenKey
219 ********************************************************************/
221 WERROR _winreg_OpenKey(struct pipes_struct *p,
222 struct winreg_OpenKey *r)
224 struct registry_key *parent = find_regkey_by_hnd(p, r->in.parent_handle );
226 if ( !parent )
227 return WERR_BADFID;
229 return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
232 /*******************************************************************
233 _winreg_QueryValue
234 ********************************************************************/
236 WERROR _winreg_QueryValue(struct pipes_struct *p,
237 struct winreg_QueryValue *r)
239 WERROR status = WERR_BADFILE;
240 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
241 prs_struct prs_hkpd;
243 uint8_t *outbuf = NULL;
244 uint32_t outbuf_size = 0;
246 bool free_buf = False;
247 bool free_prs = False;
249 if ( !regkey )
250 return WERR_BADFID;
252 if (r->in.value_name->name == NULL) {
253 return WERR_INVALID_PARAM;
256 if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
257 return WERR_INVALID_PARAM;
260 DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
261 DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
263 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
264 if(regkey->key->type == REG_KEY_HKPD)
266 if (strequal(r->in.value_name->name, "Global")) {
267 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
268 return WERR_NOMEM;
269 status = reg_perfcount_get_hkpd(
270 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
271 outbuf = (uint8_t *)prs_hkpd.data_p;
272 free_prs = True;
274 else if (strequal(r->in.value_name->name, "Counter 009")) {
275 outbuf_size = reg_perfcount_get_counter_names(
276 reg_perfcount_get_base_index(),
277 (char **)(void *)&outbuf);
278 free_buf = True;
280 else if (strequal(r->in.value_name->name, "Explain 009")) {
281 outbuf_size = reg_perfcount_get_counter_help(
282 reg_perfcount_get_base_index(),
283 (char **)(void *)&outbuf);
284 free_buf = True;
286 else if (isdigit(r->in.value_name->name[0])) {
287 /* we probably have a request for a specific object
288 * here */
289 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
290 return WERR_NOMEM;
291 status = reg_perfcount_get_hkpd(
292 &prs_hkpd, *r->in.data_size, &outbuf_size,
293 r->in.value_name->name);
294 outbuf = (uint8_t *)prs_hkpd.data_p;
295 free_prs = True;
297 else {
298 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
299 r->in.value_name->name));
300 return WERR_BADFILE;
303 *r->out.type = REG_BINARY;
305 else {
306 struct registry_value *val;
308 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
309 &val);
310 if (!W_ERROR_IS_OK(status)) {
312 DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
313 win_errstr(status)));
315 if (r->out.data_size) {
316 *r->out.data_size = 0;
318 if (r->out.data_length) {
319 *r->out.data_length = 0;
321 return status;
324 outbuf = val->data.data;
325 outbuf_size = val->data.length;
326 *r->out.type = val->type;
329 status = WERR_BADFILE;
331 if (*r->in.data_size < outbuf_size) {
332 *r->out.data_size = outbuf_size;
333 status = r->in.data ? WERR_MORE_DATA : WERR_OK;
334 } else {
335 *r->out.data_length = outbuf_size;
336 *r->out.data_size = outbuf_size;
337 if (r->out.data) {
338 memcpy(r->out.data, outbuf, outbuf_size);
340 status = WERR_OK;
343 if (free_prs) prs_mem_free(&prs_hkpd);
344 if (free_buf) SAFE_FREE(outbuf);
346 return status;
349 /*****************************************************************************
350 _winreg_QueryInfoKey
351 ****************************************************************************/
353 WERROR _winreg_QueryInfoKey(struct pipes_struct *p,
354 struct winreg_QueryInfoKey *r)
356 WERROR status = WERR_OK;
357 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
359 if ( !regkey )
360 return WERR_BADFID;
362 r->out.classname->name = NULL;
364 status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
365 r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
366 r->out.max_valbufsize, r->out.secdescsize,
367 r->out.last_changed_time);
368 if (!W_ERROR_IS_OK(status)) {
369 return status;
373 * These calculations account for the registry buffers being
374 * UTF-16. They are inexact at best, but so far they worked.
377 *r->out.max_subkeylen *= 2;
379 *r->out.max_valnamelen += 1;
380 *r->out.max_valnamelen *= 2;
382 return WERR_OK;
386 /*****************************************************************************
387 _winreg_GetVersion
388 ****************************************************************************/
390 WERROR _winreg_GetVersion(struct pipes_struct *p,
391 struct winreg_GetVersion *r)
393 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
395 if ( !regkey )
396 return WERR_BADFID;
398 return reg_getversion(r->out.version);
402 /*****************************************************************************
403 _winreg_EnumKey
404 ****************************************************************************/
406 WERROR _winreg_EnumKey(struct pipes_struct *p,
407 struct winreg_EnumKey *r)
409 WERROR err = WERR_OK;
410 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
412 if ( !key )
413 return WERR_BADFID;
415 if ( !r->in.name || !r->in.keyclass )
416 return WERR_INVALID_PARAM;
418 DEBUG(8,("_winreg_EnumKey: enumerating key [%s]\n", key->key->name));
420 err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, (char **)&r->out.name->name,
421 r->out.last_changed_time);
422 if (!W_ERROR_IS_OK(err)) {
423 return err;
425 r->out.keyclass->name = "";
426 return WERR_OK;
429 /*****************************************************************************
430 _winreg_EnumValue
431 ****************************************************************************/
433 WERROR _winreg_EnumValue(struct pipes_struct *p,
434 struct winreg_EnumValue *r)
436 WERROR err = WERR_OK;
437 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
438 char *valname = NULL;
439 struct registry_value *val = NULL;
441 if ( !key )
442 return WERR_BADFID;
444 if ( !r->in.name )
445 return WERR_INVALID_PARAM;
447 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
448 key->key->name));
450 err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
451 if (!W_ERROR_IS_OK(err)) {
452 return err;
455 if (r->out.name != NULL) {
456 r->out.name->name = valname;
459 if (r->out.type != NULL) {
460 *r->out.type = val->type;
463 if (r->out.value != NULL) {
464 if ((r->out.size == NULL) || (r->out.length == NULL)) {
465 return WERR_INVALID_PARAM;
468 if (val->data.length > *r->out.size) {
469 return WERR_MORE_DATA;
472 memcpy( r->out.value, val->data.data, val->data.length );
475 if (r->out.length != NULL) {
476 *r->out.length = val->data.length;
478 if (r->out.size != NULL) {
479 *r->out.size = val->data.length;
482 return WERR_OK;
485 /*******************************************************************
486 _winreg_InitiateSystemShutdown
487 ********************************************************************/
489 WERROR _winreg_InitiateSystemShutdown(struct pipes_struct *p,
490 struct winreg_InitiateSystemShutdown *r)
492 struct winreg_InitiateSystemShutdownEx s;
494 s.in.hostname = r->in.hostname;
495 s.in.message = r->in.message;
496 s.in.timeout = r->in.timeout;
497 s.in.force_apps = r->in.force_apps;
498 s.in.do_reboot = r->in.do_reboot;
499 s.in.reason = 0;
501 /* thunk down to _winreg_InitiateSystemShutdownEx()
502 (just returns a status) */
504 return _winreg_InitiateSystemShutdownEx( p, &s );
507 /*******************************************************************
508 _winreg_InitiateSystemShutdownEx
509 ********************************************************************/
511 #define SHUTDOWN_R_STRING "-r"
512 #define SHUTDOWN_F_STRING "-f"
515 WERROR _winreg_InitiateSystemShutdownEx(struct pipes_struct *p,
516 struct winreg_InitiateSystemShutdownEx *r)
518 char *shutdown_script = NULL;
519 char *msg = NULL;
520 char *chkmsg = NULL;
521 fstring str_timeout;
522 fstring str_reason;
523 fstring do_reboot;
524 fstring f;
525 int ret = -1;
526 bool can_shutdown = false;
528 shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
529 if (!shutdown_script) {
530 return WERR_NOMEM;
532 if (!*shutdown_script) {
533 return WERR_ACCESS_DENIED;
536 /* pull the message string and perform necessary sanity checks on it */
538 if ( r->in.message && r->in.message->string ) {
539 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
540 return WERR_NOMEM;
542 chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
543 if (!chkmsg) {
544 return WERR_NOMEM;
546 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
549 fstr_sprintf(str_timeout, "%d", r->in.timeout);
550 fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
551 fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
552 fstr_sprintf(str_reason, "%d", r->in.reason );
554 shutdown_script = talloc_all_string_sub(p->mem_ctx,
555 shutdown_script, "%z", chkmsg ? chkmsg : "");
556 if (!shutdown_script) {
557 return WERR_NOMEM;
559 shutdown_script = talloc_all_string_sub(p->mem_ctx,
560 shutdown_script, "%t", str_timeout);
561 if (!shutdown_script) {
562 return WERR_NOMEM;
564 shutdown_script = talloc_all_string_sub(p->mem_ctx,
565 shutdown_script, "%r", do_reboot);
566 if (!shutdown_script) {
567 return WERR_NOMEM;
569 shutdown_script = talloc_all_string_sub(p->mem_ctx,
570 shutdown_script, "%f", f);
571 if (!shutdown_script) {
572 return WERR_NOMEM;
574 shutdown_script = talloc_all_string_sub(p->mem_ctx,
575 shutdown_script, "%x", str_reason);
576 if (!shutdown_script) {
577 return WERR_NOMEM;
580 can_shutdown = security_token_has_privilege(p->server_info->ptok, SEC_PRIV_REMOTE_SHUTDOWN);
582 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
583 Take the error return from the script and provide it as the Windows return code. */
585 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
587 if ( can_shutdown )
588 become_root();
590 ret = smbrun( shutdown_script, NULL );
592 if ( can_shutdown )
593 unbecome_root();
595 /********** END SeRemoteShutdownPrivilege BLOCK **********/
597 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
598 shutdown_script, ret));
600 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
603 /*******************************************************************
604 _winreg_AbortSystemShutdown
605 ********************************************************************/
607 WERROR _winreg_AbortSystemShutdown(struct pipes_struct *p,
608 struct winreg_AbortSystemShutdown *r)
610 const char *abort_shutdown_script = lp_abort_shutdown_script();
611 int ret = -1;
612 bool can_shutdown = false;
614 if (!*abort_shutdown_script)
615 return WERR_ACCESS_DENIED;
617 can_shutdown = security_token_has_privilege(p->server_info->ptok, SEC_PRIV_REMOTE_SHUTDOWN);
619 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
621 if ( can_shutdown )
622 become_root();
624 ret = smbrun( abort_shutdown_script, NULL );
626 if ( can_shutdown )
627 unbecome_root();
629 /********** END SeRemoteShutdownPrivilege BLOCK **********/
631 DEBUG(3,("_winreg_AbortSystemShutdown: Running the command `%s' gave %d\n",
632 abort_shutdown_script, ret));
634 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
637 /*******************************************************************
638 ********************************************************************/
640 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
642 char *p = NULL;
643 int num_services = lp_numservices();
644 int snum = -1;
645 const char *share_path = NULL;
646 char *fname = *pp_fname;
648 /* convert to a unix path, stripping the C:\ along the way */
650 if (!(p = valid_share_pathname(ctx, fname))) {
651 return -1;
654 /* has to exist within a valid file share */
656 for (snum=0; snum<num_services; snum++) {
657 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
658 continue;
661 share_path = lp_pathname(snum);
663 /* make sure we have a path (e.g. [homes] ) */
664 if (strlen(share_path) == 0) {
665 continue;
668 if (strncmp(share_path, p, strlen(share_path)) == 0) {
669 break;
673 *pp_fname = p;
674 return (snum < num_services) ? snum : -1;
677 /*******************************************************************
678 _winreg_RestoreKey
679 ********************************************************************/
681 WERROR _winreg_RestoreKey(struct pipes_struct *p,
682 struct winreg_RestoreKey *r)
684 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
685 char *fname = NULL;
686 int snum = -1;
688 if ( !regkey )
689 return WERR_BADFID;
691 if ( !r->in.filename || !r->in.filename->name )
692 return WERR_INVALID_PARAM;
694 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
695 if (!fname) {
696 return WERR_NOMEM;
699 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
700 "\"%s\"\n", regkey->key->name, fname));
702 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
703 return WERR_OBJECT_PATH_INVALID;
705 /* user must posses SeRestorePrivilege for this this proceed */
707 if ( !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_RESTORE)) {
708 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 = NULL;
774 WERROR result = WERR_OK;
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 = NULL;
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 = WERR_OK;
863 struct security_descriptor *secdesc = NULL;
864 uint8 *data = NULL;
865 size_t len = 0;
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 = NULL;
907 WERROR err = WERR_OK;
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 = 0;
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 = data_blob_null;
1053 int i = 0;
1054 WERROR err = WERR_OK;
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;