s3-srvsvc: Use struct pipes_struct.
[Samba/gbeck.git] / source3 / rpc_server / srv_winreg_nt.c
blob73d2775b16dedec4ea694f2fd5c1001c264f657f
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(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( pipes_struct *p, struct policy_handle *hnd,
58 struct registry_key *parent,
59 const char *subkeyname,
60 uint32 access_desired )
62 WERROR result = WERR_OK;
63 struct registry_key *key;
65 if (parent == NULL) {
66 result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
67 p->server_info->ptok, &key);
69 else {
70 result = reg_openkey(p->mem_ctx, parent, subkeyname,
71 access_desired, &key);
74 if ( !W_ERROR_IS_OK(result) ) {
75 return result;
78 if ( !create_policy_hnd( p, hnd, key ) ) {
79 return WERR_BADFILE;
82 return WERR_OK;
85 /*******************************************************************
86 Function for open a new registry handle and creating a handle
87 Note that P should be valid & hnd should already have space
88 *******************************************************************/
90 static bool close_registry_key(pipes_struct *p, struct policy_handle *hnd)
92 struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
94 if ( !regkey ) {
95 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
96 OUR_HANDLE(hnd)));
97 return False;
100 close_policy_hnd(p, hnd);
102 return True;
105 /********************************************************************
106 _winreg_CloseKey
107 ********************************************************************/
109 WERROR _winreg_CloseKey(pipes_struct *p, struct winreg_CloseKey *r)
111 /* close the policy handle */
113 if (!close_registry_key(p, r->in.handle))
114 return WERR_BADFID;
116 ZERO_STRUCTP(r->out.handle);
118 return WERR_OK;
121 /*******************************************************************
122 _winreg_OpenHKLM
123 ********************************************************************/
125 WERROR _winreg_OpenHKLM(pipes_struct *p, struct winreg_OpenHKLM *r)
127 return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
130 /*******************************************************************
131 _winreg_OpenHKPD
132 ********************************************************************/
134 WERROR _winreg_OpenHKPD(pipes_struct *p, struct winreg_OpenHKPD *r)
136 return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
139 /*******************************************************************
140 _winreg_OpenHKPT
141 ********************************************************************/
143 WERROR _winreg_OpenHKPT(pipes_struct *p, struct winreg_OpenHKPT *r)
145 return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
148 /*******************************************************************
149 _winreg_OpenHKCR
150 ********************************************************************/
152 WERROR _winreg_OpenHKCR(pipes_struct *p, struct winreg_OpenHKCR *r)
154 return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
157 /*******************************************************************
158 _winreg_OpenHKU
159 ********************************************************************/
161 WERROR _winreg_OpenHKU(pipes_struct *p, struct winreg_OpenHKU *r)
163 return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
166 /*******************************************************************
167 _winreg_OpenHKCU
168 ********************************************************************/
170 WERROR _winreg_OpenHKCU(pipes_struct *p, struct winreg_OpenHKCU *r)
172 return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
175 /*******************************************************************
176 _winreg_OpenHKCC
177 ********************************************************************/
179 WERROR _winreg_OpenHKCC(pipes_struct *p, struct winreg_OpenHKCC *r)
181 return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
184 /*******************************************************************
185 _winreg_OpenHKDD
186 ********************************************************************/
188 WERROR _winreg_OpenHKDD(pipes_struct *p, struct winreg_OpenHKDD *r)
190 return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
193 /*******************************************************************
194 _winreg_OpenHKPN
195 ********************************************************************/
197 WERROR _winreg_OpenHKPN(pipes_struct *p, struct winreg_OpenHKPN *r)
199 return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
202 /*******************************************************************
203 _winreg_OpenKey
204 ********************************************************************/
206 WERROR _winreg_OpenKey(pipes_struct *p, struct winreg_OpenKey *r)
208 struct registry_key *parent = find_regkey_by_hnd(p, r->in.parent_handle );
210 if ( !parent )
211 return WERR_BADFID;
213 return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
216 /*******************************************************************
217 _winreg_QueryValue
218 ********************************************************************/
220 WERROR _winreg_QueryValue(pipes_struct *p, struct winreg_QueryValue *r)
222 WERROR status = WERR_BADFILE;
223 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
224 prs_struct prs_hkpd;
226 uint8_t *outbuf;
227 uint32_t outbuf_size;
229 bool free_buf = False;
230 bool free_prs = False;
232 if ( !regkey )
233 return WERR_BADFID;
235 if (r->in.value_name->name == NULL) {
236 return WERR_INVALID_PARAM;
239 if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
240 return WERR_INVALID_PARAM;
243 DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
244 DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
246 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
247 if(regkey->key->type == REG_KEY_HKPD)
249 if (strequal(r->in.value_name->name, "Global")) {
250 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
251 return WERR_NOMEM;
252 status = reg_perfcount_get_hkpd(
253 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
254 outbuf = (uint8_t *)prs_hkpd.data_p;
255 free_prs = True;
257 else if (strequal(r->in.value_name->name, "Counter 009")) {
258 outbuf_size = reg_perfcount_get_counter_names(
259 reg_perfcount_get_base_index(),
260 (char **)(void *)&outbuf);
261 free_buf = True;
263 else if (strequal(r->in.value_name->name, "Explain 009")) {
264 outbuf_size = reg_perfcount_get_counter_help(
265 reg_perfcount_get_base_index(),
266 (char **)(void *)&outbuf);
267 free_buf = True;
269 else if (isdigit(r->in.value_name->name[0])) {
270 /* we probably have a request for a specific object
271 * here */
272 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
273 return WERR_NOMEM;
274 status = reg_perfcount_get_hkpd(
275 &prs_hkpd, *r->in.data_size, &outbuf_size,
276 r->in.value_name->name);
277 outbuf = (uint8_t *)prs_hkpd.data_p;
278 free_prs = True;
280 else {
281 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
282 r->in.value_name->name));
283 return WERR_BADFILE;
286 *r->out.type = REG_BINARY;
288 else {
289 struct registry_value *val;
291 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
292 &val);
293 if (!W_ERROR_IS_OK(status)) {
295 DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
296 win_errstr(status)));
298 if (r->out.data_size) {
299 *r->out.data_size = 0;
301 if (r->out.data_length) {
302 *r->out.data_length = 0;
304 return status;
307 outbuf = val->data.data;
308 outbuf_size = val->data.length;
309 *r->out.type = val->type;
312 status = WERR_BADFILE;
314 if (*r->in.data_size < outbuf_size) {
315 *r->out.data_size = outbuf_size;
316 status = r->in.data ? WERR_MORE_DATA : WERR_OK;
317 } else {
318 *r->out.data_length = outbuf_size;
319 *r->out.data_size = outbuf_size;
320 if (r->out.data) {
321 memcpy(r->out.data, outbuf, outbuf_size);
323 status = WERR_OK;
326 if (free_prs) prs_mem_free(&prs_hkpd);
327 if (free_buf) SAFE_FREE(outbuf);
329 return status;
332 /*****************************************************************************
333 _winreg_QueryInfoKey
334 ****************************************************************************/
336 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct winreg_QueryInfoKey *r)
338 WERROR status = WERR_OK;
339 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
341 if ( !regkey )
342 return WERR_BADFID;
344 r->out.classname->name = NULL;
346 status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
347 r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
348 r->out.max_valbufsize, r->out.secdescsize,
349 r->out.last_changed_time);
350 if (!W_ERROR_IS_OK(status)) {
351 return status;
355 * These calculations account for the registry buffers being
356 * UTF-16. They are inexact at best, but so far they worked.
359 *r->out.max_subkeylen *= 2;
361 *r->out.max_valnamelen += 1;
362 *r->out.max_valnamelen *= 2;
364 return WERR_OK;
368 /*****************************************************************************
369 _winreg_GetVersion
370 ****************************************************************************/
372 WERROR _winreg_GetVersion(pipes_struct *p, struct winreg_GetVersion *r)
374 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
376 if ( !regkey )
377 return WERR_BADFID;
379 return reg_getversion(r->out.version);
383 /*****************************************************************************
384 _winreg_EnumKey
385 ****************************************************************************/
387 WERROR _winreg_EnumKey(pipes_struct *p, struct winreg_EnumKey *r)
389 WERROR err;
390 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
392 if ( !key )
393 return WERR_BADFID;
395 if ( !r->in.name || !r->in.keyclass )
396 return WERR_INVALID_PARAM;
398 DEBUG(8,("_winreg_EnumKey: enumerating key [%s]\n", key->key->name));
400 err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, (char **)&r->out.name->name,
401 r->out.last_changed_time);
402 if (!W_ERROR_IS_OK(err)) {
403 return err;
405 r->out.keyclass->name = "";
406 return WERR_OK;
409 /*****************************************************************************
410 _winreg_EnumValue
411 ****************************************************************************/
413 WERROR _winreg_EnumValue(pipes_struct *p, struct winreg_EnumValue *r)
415 WERROR err;
416 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
417 char *valname;
418 struct registry_value *val;
420 if ( !key )
421 return WERR_BADFID;
423 if ( !r->in.name )
424 return WERR_INVALID_PARAM;
426 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
427 key->key->name));
429 err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
430 if (!W_ERROR_IS_OK(err)) {
431 return err;
434 if (r->out.name != NULL) {
435 r->out.name->name = valname;
438 if (r->out.type != NULL) {
439 *r->out.type = val->type;
442 if (r->out.value != NULL) {
443 if ((r->out.size == NULL) || (r->out.length == NULL)) {
444 return WERR_INVALID_PARAM;
447 if (val->data.length > *r->out.size) {
448 return WERR_MORE_DATA;
451 memcpy( r->out.value, val->data.data, val->data.length );
454 if (r->out.length != NULL) {
455 *r->out.length = val->data.length;
457 if (r->out.size != NULL) {
458 *r->out.size = val->data.length;
461 return WERR_OK;
464 /*******************************************************************
465 _winreg_InitiateSystemShutdown
466 ********************************************************************/
468 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, struct winreg_InitiateSystemShutdown *r)
470 struct winreg_InitiateSystemShutdownEx s;
472 s.in.hostname = r->in.hostname;
473 s.in.message = r->in.message;
474 s.in.timeout = r->in.timeout;
475 s.in.force_apps = r->in.force_apps;
476 s.in.do_reboot = r->in.do_reboot;
477 s.in.reason = 0;
479 /* thunk down to _winreg_InitiateSystemShutdownEx()
480 (just returns a status) */
482 return _winreg_InitiateSystemShutdownEx( p, &s );
485 /*******************************************************************
486 _winreg_InitiateSystemShutdownEx
487 ********************************************************************/
489 #define SHUTDOWN_R_STRING "-r"
490 #define SHUTDOWN_F_STRING "-f"
493 WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateSystemShutdownEx *r)
495 char *shutdown_script = NULL;
496 char *msg = NULL;
497 char *chkmsg = NULL;
498 fstring str_timeout;
499 fstring str_reason;
500 fstring do_reboot;
501 fstring f;
502 int ret;
503 bool can_shutdown;
505 shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
506 if (!shutdown_script) {
507 return WERR_NOMEM;
509 if (!*shutdown_script) {
510 return WERR_ACCESS_DENIED;
513 /* pull the message string and perform necessary sanity checks on it */
515 if ( r->in.message && r->in.message->string ) {
516 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
517 return WERR_NOMEM;
519 chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
520 if (!chkmsg) {
521 return WERR_NOMEM;
523 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
526 fstr_sprintf(str_timeout, "%d", r->in.timeout);
527 fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
528 fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
529 fstr_sprintf(str_reason, "%d", r->in.reason );
531 shutdown_script = talloc_all_string_sub(p->mem_ctx,
532 shutdown_script, "%z", chkmsg ? chkmsg : "");
533 if (!shutdown_script) {
534 return WERR_NOMEM;
536 shutdown_script = talloc_all_string_sub(p->mem_ctx,
537 shutdown_script, "%t", str_timeout);
538 if (!shutdown_script) {
539 return WERR_NOMEM;
541 shutdown_script = talloc_all_string_sub(p->mem_ctx,
542 shutdown_script, "%r", do_reboot);
543 if (!shutdown_script) {
544 return WERR_NOMEM;
546 shutdown_script = talloc_all_string_sub(p->mem_ctx,
547 shutdown_script, "%f", f);
548 if (!shutdown_script) {
549 return WERR_NOMEM;
551 shutdown_script = talloc_all_string_sub(p->mem_ctx,
552 shutdown_script, "%x", str_reason);
553 if (!shutdown_script) {
554 return WERR_NOMEM;
557 can_shutdown = user_has_privileges( p->server_info->ptok,
558 &se_remote_shutdown );
560 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
561 Take the error return from the script and provide it as the Windows return code. */
563 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
565 if ( can_shutdown )
566 become_root();
568 ret = smbrun( shutdown_script, NULL );
570 if ( can_shutdown )
571 unbecome_root();
573 /********** END SeRemoteShutdownPrivilege BLOCK **********/
575 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
576 shutdown_script, ret));
578 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
581 /*******************************************************************
582 _winreg_AbortSystemShutdown
583 ********************************************************************/
585 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, struct winreg_AbortSystemShutdown *r)
587 const char *abort_shutdown_script;
588 int ret;
589 bool can_shutdown;
591 abort_shutdown_script = lp_abort_shutdown_script();
593 if (!*abort_shutdown_script)
594 return WERR_ACCESS_DENIED;
596 can_shutdown = user_has_privileges( p->server_info->ptok,
597 &se_remote_shutdown );
599 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
601 if ( can_shutdown )
602 become_root();
604 ret = smbrun( abort_shutdown_script, NULL );
606 if ( can_shutdown )
607 unbecome_root();
609 /********** END SeRemoteShutdownPrivilege BLOCK **********/
611 DEBUG(3,("_winreg_AbortSystemShutdown: Running the command `%s' gave %d\n",
612 abort_shutdown_script, ret));
614 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
617 /*******************************************************************
618 ********************************************************************/
620 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
622 char *p = NULL;
623 int num_services = lp_numservices();
624 int snum = -1;
625 const char *share_path;
626 char *fname = *pp_fname;
628 /* convert to a unix path, stripping the C:\ along the way */
630 if (!(p = valid_share_pathname(ctx, fname))) {
631 return -1;
634 /* has to exist within a valid file share */
636 for (snum=0; snum<num_services; snum++) {
637 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
638 continue;
641 share_path = lp_pathname(snum);
643 /* make sure we have a path (e.g. [homes] ) */
644 if (strlen(share_path) == 0) {
645 continue;
648 if (strncmp(share_path, p, strlen(share_path)) == 0) {
649 break;
653 *pp_fname = p;
654 return (snum < num_services) ? snum : -1;
657 /*******************************************************************
658 _winreg_RestoreKey
659 ********************************************************************/
661 WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
663 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
664 char *fname = NULL;
665 int snum;
667 if ( !regkey )
668 return WERR_BADFID;
670 if ( !r->in.filename || !r->in.filename->name )
671 return WERR_INVALID_PARAM;
673 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
674 if (!fname) {
675 return WERR_NOMEM;
678 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
679 "\"%s\"\n", regkey->key->name, fname));
681 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
682 return WERR_OBJECT_PATH_INVALID;
684 /* user must posses SeRestorePrivilege for this this proceed */
686 if ( !user_has_privileges( p->server_info->ptok, &se_restore ) )
687 return WERR_ACCESS_DENIED;
689 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
690 regkey->key->name, fname, lp_servicename(snum) ));
692 return reg_restorekey(regkey, fname);
695 /*******************************************************************
696 _winreg_SaveKey
697 ********************************************************************/
699 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
701 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
702 char *fname = NULL;
703 int snum = -1;
705 if ( !regkey )
706 return WERR_BADFID;
708 if ( !r->in.filename || !r->in.filename->name )
709 return WERR_INVALID_PARAM;
711 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
712 if (!fname) {
713 return WERR_NOMEM;
716 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
717 regkey->key->name, fname));
719 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
720 return WERR_OBJECT_PATH_INVALID;
722 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
723 regkey->key->name, fname, lp_servicename(snum) ));
725 return reg_savekey(regkey, fname);
728 /*******************************************************************
729 _winreg_SaveKeyEx
730 ********************************************************************/
732 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
734 /* fill in your code here if you think this call should
735 do anything */
737 p->rng_fault_state = True;
738 return WERR_NOT_SUPPORTED;
741 /*******************************************************************
742 _winreg_CreateKey
743 ********************************************************************/
745 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
747 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
748 struct registry_key *new_key;
749 WERROR result;
751 if ( !parent )
752 return WERR_BADFID;
754 DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
755 "subkey name '%s'\n", parent->key->name, r->in.name.name));
757 result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
758 &new_key, r->out.action_taken);
759 if (!W_ERROR_IS_OK(result)) {
760 return result;
763 if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
764 TALLOC_FREE(new_key);
765 return WERR_BADFILE;
768 return WERR_OK;
771 /*******************************************************************
772 _winreg_SetValue
773 ********************************************************************/
775 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
777 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
778 struct registry_value *val;
780 if ( !key )
781 return WERR_BADFID;
783 DEBUG(8,("_winreg_SetValue: Setting value for [%s:%s]\n",
784 key->key->name, r->in.name.name));
786 val = talloc_zero(p->mem_ctx, struct registry_value);
787 if (val == NULL) {
788 return WERR_NOMEM;
791 val->type = r->in.type;
792 val->data = data_blob_talloc(p->mem_ctx, r->in.data, r->in.size);
794 return reg_setvalue(key, r->in.name.name, val);
797 /*******************************************************************
798 _winreg_DeleteKey
799 ********************************************************************/
801 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
803 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
805 if ( !parent )
806 return WERR_BADFID;
808 return reg_deletekey(parent, r->in.key.name);
812 /*******************************************************************
813 _winreg_DeleteValue
814 ********************************************************************/
816 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
818 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
820 if ( !key )
821 return WERR_BADFID;
823 return reg_deletevalue(key, r->in.value.name);
826 /*******************************************************************
827 _winreg_GetKeySecurity
828 ********************************************************************/
830 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
832 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
833 WERROR err;
834 struct security_descriptor *secdesc;
835 uint8 *data;
836 size_t len;
838 if ( !key )
839 return WERR_BADFID;
841 /* access checks first */
843 if ( !(key->key->access_granted & SEC_STD_READ_CONTROL) )
844 return WERR_ACCESS_DENIED;
846 err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
847 if (!W_ERROR_IS_OK(err)) {
848 return err;
851 err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
852 &data, &len));
853 if (!W_ERROR_IS_OK(err)) {
854 return err;
857 if (len > r->out.sd->size) {
858 r->out.sd->size = len;
859 return WERR_INSUFFICIENT_BUFFER;
862 r->out.sd->size = len;
863 r->out.sd->len = len;
864 r->out.sd->data = data;
866 return WERR_OK;
869 /*******************************************************************
870 _winreg_SetKeySecurity
871 ********************************************************************/
873 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
875 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
876 struct security_descriptor *secdesc;
877 WERROR err;
879 if ( !key )
880 return WERR_BADFID;
882 /* access checks first */
884 if ( !(key->key->access_granted & SEC_STD_WRITE_DAC) )
885 return WERR_ACCESS_DENIED;
887 err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
888 r->in.sd->len, &secdesc));
889 if (!W_ERROR_IS_OK(err)) {
890 return err;
893 return reg_setkeysecurity(key, secdesc);
896 /*******************************************************************
897 _winreg_FlushKey
898 ********************************************************************/
900 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
902 /* I'm just replying OK because there's not a lot
903 here I see to do i --jerry */
905 return WERR_OK;
908 /*******************************************************************
909 _winreg_UnLoadKey
910 ********************************************************************/
912 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
914 /* fill in your code here if you think this call should
915 do anything */
917 p->rng_fault_state = True;
918 return WERR_NOT_SUPPORTED;
921 /*******************************************************************
922 _winreg_ReplaceKey
923 ********************************************************************/
925 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
927 /* fill in your code here if you think this call should
928 do anything */
930 p->rng_fault_state = True;
931 return WERR_NOT_SUPPORTED;
934 /*******************************************************************
935 _winreg_LoadKey
936 ********************************************************************/
938 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
940 /* fill in your code here if you think this call should
941 do anything */
943 p->rng_fault_state = True;
944 return WERR_NOT_SUPPORTED;
947 /*******************************************************************
948 _winreg_NotifyChangeKeyValue
949 ********************************************************************/
951 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
953 return WERR_NOT_SUPPORTED;
956 /*******************************************************************
957 _winreg_QueryMultipleValues
958 ********************************************************************/
960 WERROR _winreg_QueryMultipleValues(pipes_struct *p,
961 struct winreg_QueryMultipleValues *r)
963 struct winreg_QueryMultipleValues2 r2;
964 uint32_t needed;
966 r2.in.key_handle = r->in.key_handle;
967 r2.in.values_in = r->in.values_in;
968 r2.in.num_values = r->in.num_values;
969 r2.in.offered = r->in.buffer_size;
970 r2.in.buffer = r->in.buffer;
971 r2.out.values_out = r->out.values_out;
972 r2.out.needed = &needed;
973 r2.out.buffer = r->out.buffer;
975 return _winreg_QueryMultipleValues2(p, &r2);
978 /*******************************************************************
979 ********************************************************************/
981 static WERROR construct_multiple_entry(TALLOC_CTX *mem_ctx,
982 const char *valuename,
983 uint32_t value_length,
984 uint32_t offset,
985 enum winreg_Type type,
986 struct QueryMultipleValue *r)
988 r->ve_valuename = talloc_zero(mem_ctx, struct winreg_ValNameBuf);
989 if (r->ve_valuename == NULL) {
990 return WERR_NOMEM;
993 r->ve_valuename->name = talloc_strdup(r->ve_valuename, valuename ? valuename : "");
994 if (r->ve_valuename->name == NULL) {
995 return WERR_NOMEM;
998 r->ve_valuename->size = strlen_m_term(r->ve_valuename->name)*2;
999 r->ve_valuelen = value_length;
1000 r->ve_valueptr = offset;
1001 r->ve_type = type;
1003 return WERR_OK;
1006 /*******************************************************************
1007 _winreg_QueryMultipleValues2
1008 ********************************************************************/
1010 WERROR _winreg_QueryMultipleValues2(pipes_struct *p,
1011 struct winreg_QueryMultipleValues2 *r)
1013 struct registry_key *regkey = find_regkey_by_hnd(p, r->in.key_handle);
1014 struct registry_value *vals = NULL;
1015 const char **names = NULL;
1016 uint32_t offset = 0, num_vals = 0;
1017 DATA_BLOB result;
1018 int i;
1019 WERROR err;
1021 if (!regkey) {
1022 return WERR_BADFID;
1025 names = talloc_zero_array(p->mem_ctx, const char *, r->in.num_values);
1026 if (names == NULL) {
1027 return WERR_NOMEM;
1030 for (i=0; i < r->in.num_values; i++) {
1031 if (r->in.values_in[i].ve_valuename &&
1032 r->in.values_in[i].ve_valuename->name) {
1033 names[i] = talloc_strdup(names,
1034 r->in.values_in[i].ve_valuename->name);
1035 if (names[i] == NULL) {
1036 return WERR_NOMEM;
1041 err = reg_querymultiplevalues(p->mem_ctx, regkey,
1042 r->in.num_values, names,
1043 &num_vals, &vals);
1044 if (!W_ERROR_IS_OK(err)) {
1045 return err;
1048 result = data_blob_talloc(p->mem_ctx, NULL, 0);
1050 for (i=0; i < r->in.num_values; i++) {
1051 const char *valuename = NULL;
1053 if (vals[i].data.length > 0) {
1054 if (!data_blob_append(p->mem_ctx, &result,
1055 vals[i].data.data,
1056 vals[i].data.length)) {
1057 return WERR_NOMEM;
1061 if (r->in.values_in[i].ve_valuename &&
1062 r->in.values_in[i].ve_valuename->name) {
1063 valuename = r->in.values_in[i].ve_valuename->name;
1066 err = construct_multiple_entry(r->out.values_out,
1067 valuename,
1068 vals[i].data.length,
1069 offset,
1070 vals[i].type,
1071 &r->out.values_out[i]);
1072 if (!W_ERROR_IS_OK(err)) {
1073 return err;
1076 offset += vals[i].data.length;
1079 *r->out.needed = result.length;
1081 if (r->in.num_values != num_vals) {
1082 return WERR_BADFILE;
1085 if (*r->in.offered >= *r->out.needed) {
1086 if (r->out.buffer) {
1087 memcpy(r->out.buffer, result.data, MIN(result.length, *r->in.offered));
1089 return WERR_OK;
1090 } else {
1091 return WERR_MORE_DATA;
1095 /*******************************************************************
1096 _winreg_DeleteKeyEx
1097 ********************************************************************/
1099 WERROR _winreg_DeleteKeyEx(pipes_struct *p, struct winreg_DeleteKeyEx *r)
1101 /* fill in your code here if you think this call should
1102 do anything */
1104 p->rng_fault_state = True;
1105 return WERR_NOT_SUPPORTED;