Revert "s3:smbd: set req->smb2req->compat_chain_fsp in file_fsp()"
[Samba/gebeck_regimport.git] / source3 / rpc_server / winreg / srv_winreg_nt.c
blob6fee5b6acd944e30f7609e496e4cea1eda57817e
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
5 * Copyright (C) Gerald Carter 2002-2006.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 /* Implementation of registry functions. */
23 #include "includes.h"
24 #include "ntdomain.h"
25 #include "../librpc/gen_ndr/srv_winreg.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"
31 #include "auth.h"
32 #include "lib/privileges.h"
33 #include "libcli/security/secdesc.h"
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_RPC_SRV
38 /******************************************************************
39 Find a registry key handle and return a struct registry_key *
40 *****************************************************************/
42 static struct registry_key *find_regkey_by_hnd(struct pipes_struct *p,
43 struct policy_handle *hnd)
45 struct registry_key *regkey = NULL;
47 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) {
48 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
49 return NULL;
52 return regkey;
55 /*******************************************************************
56 Function for open a new registry handle and creating a handle
57 Note that P should be valid & hnd should already have space
59 When we open a key, we store the full path to the key as
60 HK[LM|U]\<key>\<key>\...
61 *******************************************************************/
63 static WERROR open_registry_key(struct pipes_struct *p,
64 struct policy_handle *hnd,
65 struct registry_key *parent,
66 const char *subkeyname,
67 uint32_t access_desired)
69 WERROR result = WERR_OK;
70 struct registry_key *key;
72 if (parent == NULL) {
73 result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
74 p->session_info->security_token, &key);
76 else {
77 result = reg_openkey(p->mem_ctx, parent, subkeyname,
78 access_desired, &key);
81 if ( !W_ERROR_IS_OK(result) ) {
82 return result;
85 if ( !create_policy_hnd( p, hnd, key ) ) {
86 return WERR_BADFILE;
89 return WERR_OK;
92 /*******************************************************************
93 Function for open a new registry handle and creating a handle
94 Note that P should be valid & hnd should already have space
95 *******************************************************************/
97 static bool close_registry_key(struct pipes_struct *p,
98 struct policy_handle *hnd)
100 struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
102 if ( !regkey ) {
103 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
104 OUR_HANDLE(hnd)));
105 return False;
108 close_policy_hnd(p, hnd);
110 return True;
113 /********************************************************************
114 _winreg_CloseKey
115 ********************************************************************/
117 WERROR _winreg_CloseKey(struct pipes_struct *p,
118 struct winreg_CloseKey *r)
120 /* close the policy handle */
122 if (!close_registry_key(p, r->in.handle))
123 return WERR_BADFID;
125 ZERO_STRUCTP(r->out.handle);
127 return WERR_OK;
130 /*******************************************************************
131 _winreg_OpenHKLM
132 ********************************************************************/
134 WERROR _winreg_OpenHKLM(struct pipes_struct *p,
135 struct winreg_OpenHKLM *r)
137 return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
140 /*******************************************************************
141 _winreg_OpenHKPD
142 ********************************************************************/
144 WERROR _winreg_OpenHKPD(struct pipes_struct *p,
145 struct winreg_OpenHKPD *r)
147 return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
150 /*******************************************************************
151 _winreg_OpenHKPT
152 ********************************************************************/
154 WERROR _winreg_OpenHKPT(struct pipes_struct *p,
155 struct winreg_OpenHKPT *r)
157 return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
160 /*******************************************************************
161 _winreg_OpenHKCR
162 ********************************************************************/
164 WERROR _winreg_OpenHKCR(struct pipes_struct *p,
165 struct winreg_OpenHKCR *r)
167 return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
170 /*******************************************************************
171 _winreg_OpenHKU
172 ********************************************************************/
174 WERROR _winreg_OpenHKU(struct pipes_struct *p,
175 struct winreg_OpenHKU *r)
177 return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
180 /*******************************************************************
181 _winreg_OpenHKCU
182 ********************************************************************/
184 WERROR _winreg_OpenHKCU(struct pipes_struct *p,
185 struct winreg_OpenHKCU *r)
187 return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
190 /*******************************************************************
191 _winreg_OpenHKCC
192 ********************************************************************/
194 WERROR _winreg_OpenHKCC(struct pipes_struct *p,
195 struct winreg_OpenHKCC *r)
197 return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
200 /*******************************************************************
201 _winreg_OpenHKDD
202 ********************************************************************/
204 WERROR _winreg_OpenHKDD(struct pipes_struct *p,
205 struct winreg_OpenHKDD *r)
207 return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
210 /*******************************************************************
211 _winreg_OpenHKPN
212 ********************************************************************/
214 WERROR _winreg_OpenHKPN(struct pipes_struct *p,
215 struct winreg_OpenHKPN *r)
217 return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
220 /*******************************************************************
221 _winreg_OpenKey
222 ********************************************************************/
224 WERROR _winreg_OpenKey(struct pipes_struct *p,
225 struct winreg_OpenKey *r)
227 struct registry_key *parent = find_regkey_by_hnd(p, r->in.parent_handle );
229 if ( !parent )
230 return WERR_BADFID;
232 return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
235 /*******************************************************************
236 _winreg_QueryValue
237 ********************************************************************/
239 WERROR _winreg_QueryValue(struct pipes_struct *p,
240 struct winreg_QueryValue *r)
242 WERROR status = WERR_BADFILE;
243 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
244 prs_struct prs_hkpd;
246 uint8_t *outbuf = NULL;
247 uint32_t outbuf_size = 0;
249 bool free_buf = False;
250 bool free_prs = False;
252 if ( !regkey )
253 return WERR_BADFID;
255 if (r->in.value_name->name == NULL) {
256 return WERR_INVALID_PARAM;
259 if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
260 return WERR_INVALID_PARAM;
263 DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
264 DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
266 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
267 if(regkey->key->type == REG_KEY_HKPD)
269 if (strequal(r->in.value_name->name, "Global")) {
270 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
271 return WERR_NOMEM;
272 status = reg_perfcount_get_hkpd(
273 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
274 outbuf = (uint8_t *)prs_hkpd.data_p;
275 free_prs = True;
277 else if (strequal(r->in.value_name->name, "Counter 009")) {
278 outbuf_size = reg_perfcount_get_counter_names(
279 reg_perfcount_get_base_index(),
280 (char **)(void *)&outbuf);
281 free_buf = True;
283 else if (strequal(r->in.value_name->name, "Explain 009")) {
284 outbuf_size = reg_perfcount_get_counter_help(
285 reg_perfcount_get_base_index(),
286 (char **)(void *)&outbuf);
287 free_buf = True;
289 else if (isdigit(r->in.value_name->name[0])) {
290 /* we probably have a request for a specific object
291 * here */
292 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
293 return WERR_NOMEM;
294 status = reg_perfcount_get_hkpd(
295 &prs_hkpd, *r->in.data_size, &outbuf_size,
296 r->in.value_name->name);
297 outbuf = (uint8_t *)prs_hkpd.data_p;
298 free_prs = True;
300 else {
301 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
302 r->in.value_name->name));
303 return WERR_BADFILE;
306 *r->out.type = REG_BINARY;
308 else {
309 struct registry_value *val;
311 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
312 &val);
313 if (!W_ERROR_IS_OK(status)) {
315 DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
316 win_errstr(status)));
318 if (r->out.data_size) {
319 *r->out.data_size = 0;
321 if (r->out.data_length) {
322 *r->out.data_length = 0;
324 return status;
327 outbuf = val->data.data;
328 outbuf_size = val->data.length;
329 *r->out.type = val->type;
332 status = WERR_BADFILE;
334 if (*r->in.data_size < outbuf_size) {
335 *r->out.data_size = outbuf_size;
336 status = r->in.data ? WERR_MORE_DATA : WERR_OK;
337 } else {
338 *r->out.data_length = outbuf_size;
339 *r->out.data_size = outbuf_size;
340 if (r->out.data) {
341 memcpy(r->out.data, outbuf, outbuf_size);
343 status = WERR_OK;
346 if (free_prs) prs_mem_free(&prs_hkpd);
347 if (free_buf) SAFE_FREE(outbuf);
349 return status;
352 /*****************************************************************************
353 _winreg_QueryInfoKey
354 ****************************************************************************/
356 WERROR _winreg_QueryInfoKey(struct pipes_struct *p,
357 struct winreg_QueryInfoKey *r)
359 WERROR status = WERR_OK;
360 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
362 if ( !regkey )
363 return WERR_BADFID;
365 r->out.classname->name = NULL;
367 status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
368 r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
369 r->out.max_valbufsize, r->out.secdescsize,
370 r->out.last_changed_time);
371 if (!W_ERROR_IS_OK(status)) {
372 return status;
376 * These calculations account for the registry buffers being
377 * UTF-16. They are inexact at best, but so far they worked.
380 *r->out.max_subkeylen *= 2;
382 *r->out.max_valnamelen += 1;
383 *r->out.max_valnamelen *= 2;
385 return WERR_OK;
389 /*****************************************************************************
390 _winreg_GetVersion
391 ****************************************************************************/
393 WERROR _winreg_GetVersion(struct pipes_struct *p,
394 struct winreg_GetVersion *r)
396 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
398 if ( !regkey )
399 return WERR_BADFID;
401 return reg_getversion(r->out.version);
405 /*****************************************************************************
406 _winreg_EnumKey
407 ****************************************************************************/
409 WERROR _winreg_EnumKey(struct pipes_struct *p,
410 struct winreg_EnumKey *r)
412 WERROR err = WERR_OK;
413 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
415 if ( !key )
416 return WERR_BADFID;
418 if ( !r->in.name || !r->in.keyclass )
419 return WERR_INVALID_PARAM;
421 DEBUG(8,("_winreg_EnumKey: enumerating key [%s]\n", key->key->name));
423 err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, (char **)&r->out.name->name,
424 r->out.last_changed_time);
425 if (!W_ERROR_IS_OK(err)) {
426 return err;
428 r->out.keyclass->name = "";
429 return WERR_OK;
432 /*****************************************************************************
433 _winreg_EnumValue
434 ****************************************************************************/
436 WERROR _winreg_EnumValue(struct pipes_struct *p,
437 struct winreg_EnumValue *r)
439 WERROR err = WERR_OK;
440 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
441 char *valname = NULL;
442 struct registry_value *val = NULL;
444 if ( !key )
445 return WERR_BADFID;
447 if ( !r->in.name )
448 return WERR_INVALID_PARAM;
450 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
451 key->key->name));
453 err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
454 if (!W_ERROR_IS_OK(err)) {
455 return err;
458 if (r->out.name != NULL) {
459 r->out.name->name = valname;
462 if (r->out.type != NULL) {
463 *r->out.type = val->type;
466 if (r->out.value != NULL) {
467 if ((r->out.size == NULL) || (r->out.length == NULL)) {
468 return WERR_INVALID_PARAM;
471 if (val->data.length > *r->out.size) {
472 return WERR_MORE_DATA;
475 memcpy( r->out.value, val->data.data, val->data.length );
478 if (r->out.length != NULL) {
479 *r->out.length = val->data.length;
481 if (r->out.size != NULL) {
482 *r->out.size = val->data.length;
485 return WERR_OK;
488 /*******************************************************************
489 _winreg_InitiateSystemShutdown
490 ********************************************************************/
492 WERROR _winreg_InitiateSystemShutdown(struct pipes_struct *p,
493 struct winreg_InitiateSystemShutdown *r)
495 struct winreg_InitiateSystemShutdownEx s;
497 s.in.hostname = r->in.hostname;
498 s.in.message = r->in.message;
499 s.in.timeout = r->in.timeout;
500 s.in.force_apps = r->in.force_apps;
501 s.in.do_reboot = r->in.do_reboot;
502 s.in.reason = 0;
504 /* thunk down to _winreg_InitiateSystemShutdownEx()
505 (just returns a status) */
507 return _winreg_InitiateSystemShutdownEx( p, &s );
510 /*******************************************************************
511 _winreg_InitiateSystemShutdownEx
512 ********************************************************************/
514 #define SHUTDOWN_R_STRING "-r"
515 #define SHUTDOWN_F_STRING "-f"
518 WERROR _winreg_InitiateSystemShutdownEx(struct pipes_struct *p,
519 struct winreg_InitiateSystemShutdownEx *r)
521 char *shutdown_script = NULL;
522 char *msg = NULL;
523 char *chkmsg = NULL;
524 fstring str_timeout;
525 fstring str_reason;
526 fstring do_reboot;
527 fstring f;
528 int ret = -1;
529 bool can_shutdown = false;
531 shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
532 if (!shutdown_script) {
533 return WERR_NOMEM;
535 if (!*shutdown_script) {
536 return WERR_ACCESS_DENIED;
539 /* pull the message string and perform necessary sanity checks on it */
541 if ( r->in.message && r->in.message->string ) {
542 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
543 return WERR_NOMEM;
545 chkmsg = talloc_array(p->mem_ctx, char, strlen(msg)+1);
546 if (!chkmsg) {
547 return WERR_NOMEM;
549 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
552 fstr_sprintf(str_timeout, "%d", r->in.timeout);
553 fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
554 fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
555 fstr_sprintf(str_reason, "%d", r->in.reason );
557 shutdown_script = talloc_all_string_sub(p->mem_ctx,
558 shutdown_script, "%z", chkmsg ? chkmsg : "");
559 if (!shutdown_script) {
560 return WERR_NOMEM;
562 shutdown_script = talloc_all_string_sub(p->mem_ctx,
563 shutdown_script, "%t", str_timeout);
564 if (!shutdown_script) {
565 return WERR_NOMEM;
567 shutdown_script = talloc_all_string_sub(p->mem_ctx,
568 shutdown_script, "%r", do_reboot);
569 if (!shutdown_script) {
570 return WERR_NOMEM;
572 shutdown_script = talloc_all_string_sub(p->mem_ctx,
573 shutdown_script, "%f", f);
574 if (!shutdown_script) {
575 return WERR_NOMEM;
577 shutdown_script = talloc_all_string_sub(p->mem_ctx,
578 shutdown_script, "%x", str_reason);
579 if (!shutdown_script) {
580 return WERR_NOMEM;
583 can_shutdown = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
585 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
586 Take the error return from the script and provide it as the Windows return code. */
588 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
590 if ( can_shutdown )
591 become_root();
593 ret = smbrun( shutdown_script, NULL );
595 if ( can_shutdown )
596 unbecome_root();
598 /********** END SeRemoteShutdownPrivilege BLOCK **********/
600 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
601 shutdown_script, ret));
603 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
606 /*******************************************************************
607 _winreg_AbortSystemShutdown
608 ********************************************************************/
610 WERROR _winreg_AbortSystemShutdown(struct pipes_struct *p,
611 struct winreg_AbortSystemShutdown *r)
613 const char *abort_shutdown_script = lp_abort_shutdown_script();
614 int ret = -1;
615 bool can_shutdown = false;
617 if (!*abort_shutdown_script)
618 return WERR_ACCESS_DENIED;
620 can_shutdown = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
622 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
624 if ( can_shutdown )
625 become_root();
627 ret = smbrun( abort_shutdown_script, NULL );
629 if ( can_shutdown )
630 unbecome_root();
632 /********** END SeRemoteShutdownPrivilege BLOCK **********/
634 DEBUG(3,("_winreg_AbortSystemShutdown: Running the command `%s' gave %d\n",
635 abort_shutdown_script, ret));
637 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
640 /*******************************************************************
641 ********************************************************************/
643 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
645 char *p = NULL;
646 int num_services = lp_numservices();
647 int snum = -1;
648 const char *share_path = NULL;
649 char *fname = *pp_fname;
651 /* convert to a unix path, stripping the C:\ along the way */
653 if (!(p = valid_share_pathname(ctx, fname))) {
654 return -1;
657 /* has to exist within a valid file share */
659 for (snum=0; snum<num_services; snum++) {
660 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
661 continue;
664 share_path = lp_pathname(snum);
666 /* make sure we have a path (e.g. [homes] ) */
667 if (strlen(share_path) == 0) {
668 continue;
671 if (strncmp(share_path, p, strlen(share_path)) == 0) {
672 break;
676 *pp_fname = p;
677 return (snum < num_services) ? snum : -1;
680 /*******************************************************************
681 _winreg_RestoreKey
682 ********************************************************************/
684 WERROR _winreg_RestoreKey(struct pipes_struct *p,
685 struct winreg_RestoreKey *r)
687 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
688 char *fname = NULL;
689 int snum = -1;
691 if ( !regkey )
692 return WERR_BADFID;
694 if ( !r->in.filename || !r->in.filename->name )
695 return WERR_INVALID_PARAM;
697 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
698 if (!fname) {
699 return WERR_NOMEM;
702 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
703 "\"%s\"\n", regkey->key->name, fname));
705 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
706 return WERR_OBJECT_PATH_INVALID;
708 /* user must posses SeRestorePrivilege for this this proceed */
710 if ( !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_RESTORE)) {
711 return WERR_ACCESS_DENIED;
714 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
715 regkey->key->name, fname, lp_servicename(snum) ));
717 return reg_restorekey(regkey, fname);
720 /*******************************************************************
721 _winreg_SaveKey
722 ********************************************************************/
724 WERROR _winreg_SaveKey(struct pipes_struct *p,
725 struct winreg_SaveKey *r)
727 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
728 char *fname = NULL;
729 int snum = -1;
731 if ( !regkey )
732 return WERR_BADFID;
734 if ( !r->in.filename || !r->in.filename->name )
735 return WERR_INVALID_PARAM;
737 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
738 if (!fname) {
739 return WERR_NOMEM;
742 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
743 regkey->key->name, fname));
745 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
746 return WERR_OBJECT_PATH_INVALID;
748 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
749 regkey->key->name, fname, lp_servicename(snum) ));
751 return reg_savekey(regkey, fname);
754 /*******************************************************************
755 _winreg_SaveKeyEx
756 ********************************************************************/
758 WERROR _winreg_SaveKeyEx(struct pipes_struct *p,
759 struct winreg_SaveKeyEx *r)
761 /* fill in your code here if you think this call should
762 do anything */
764 p->rng_fault_state = True;
765 return WERR_NOT_SUPPORTED;
768 /*******************************************************************
769 _winreg_CreateKey
770 ********************************************************************/
772 WERROR _winreg_CreateKey(struct pipes_struct *p,
773 struct winreg_CreateKey *r)
775 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
776 struct registry_key *new_key = NULL;
777 WERROR result = WERR_OK;
779 if ( !parent )
780 return WERR_BADFID;
782 DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
783 "subkey name '%s'\n", parent->key->name, r->in.name.name));
785 result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
786 &new_key, r->out.action_taken);
787 if (!W_ERROR_IS_OK(result)) {
788 return result;
791 if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
792 TALLOC_FREE(new_key);
793 return WERR_BADFILE;
796 return WERR_OK;
799 /*******************************************************************
800 _winreg_SetValue
801 ********************************************************************/
803 WERROR _winreg_SetValue(struct pipes_struct *p,
804 struct winreg_SetValue *r)
806 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
807 struct registry_value *val = NULL;
809 if ( !key )
810 return WERR_BADFID;
812 DEBUG(8,("_winreg_SetValue: Setting value for [%s:%s]\n",
813 key->key->name, r->in.name.name));
815 val = talloc_zero(p->mem_ctx, struct registry_value);
816 if (val == NULL) {
817 return WERR_NOMEM;
820 val->type = r->in.type;
821 val->data = data_blob_talloc(p->mem_ctx, r->in.data, r->in.size);
823 return reg_setvalue(key, r->in.name.name, val);
826 /*******************************************************************
827 _winreg_DeleteKey
828 ********************************************************************/
830 WERROR _winreg_DeleteKey(struct pipes_struct *p,
831 struct winreg_DeleteKey *r)
833 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
835 if ( !parent )
836 return WERR_BADFID;
838 return reg_deletekey(parent, r->in.key.name);
842 /*******************************************************************
843 _winreg_DeleteValue
844 ********************************************************************/
846 WERROR _winreg_DeleteValue(struct pipes_struct *p,
847 struct winreg_DeleteValue *r)
849 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
851 if ( !key )
852 return WERR_BADFID;
854 return reg_deletevalue(key, r->in.value.name);
857 /*******************************************************************
858 _winreg_GetKeySecurity
859 ********************************************************************/
861 WERROR _winreg_GetKeySecurity(struct pipes_struct *p,
862 struct winreg_GetKeySecurity *r)
864 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
865 WERROR err = WERR_OK;
866 struct security_descriptor *secdesc = NULL;
867 uint8 *data = NULL;
868 size_t len = 0;
870 if ( !key )
871 return WERR_BADFID;
873 /* access checks first */
875 if ( !(key->key->access_granted & SEC_STD_READ_CONTROL) )
876 return WERR_ACCESS_DENIED;
878 err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
879 if (!W_ERROR_IS_OK(err)) {
880 return err;
883 err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
884 &data, &len));
885 if (!W_ERROR_IS_OK(err)) {
886 return err;
889 if (len > r->out.sd->size) {
890 r->out.sd->size = len;
891 return WERR_INSUFFICIENT_BUFFER;
894 r->out.sd->size = len;
895 r->out.sd->len = len;
896 r->out.sd->data = data;
898 return WERR_OK;
901 /*******************************************************************
902 _winreg_SetKeySecurity
903 ********************************************************************/
905 WERROR _winreg_SetKeySecurity(struct pipes_struct *p,
906 struct winreg_SetKeySecurity *r)
908 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
909 struct security_descriptor *secdesc = NULL;
910 WERROR err = WERR_OK;
912 if ( !key )
913 return WERR_BADFID;
915 /* access checks first */
917 if ( !(key->key->access_granted & SEC_STD_WRITE_DAC) )
918 return WERR_ACCESS_DENIED;
920 err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
921 r->in.sd->len, &secdesc));
922 if (!W_ERROR_IS_OK(err)) {
923 return err;
926 return reg_setkeysecurity(key, secdesc);
929 /*******************************************************************
930 _winreg_FlushKey
931 ********************************************************************/
933 WERROR _winreg_FlushKey(struct pipes_struct *p,
934 struct winreg_FlushKey *r)
936 /* I'm just replying OK because there's not a lot
937 here I see to do i --jerry */
939 return WERR_OK;
942 /*******************************************************************
943 _winreg_UnLoadKey
944 ********************************************************************/
946 WERROR _winreg_UnLoadKey(struct pipes_struct *p,
947 struct winreg_UnLoadKey *r)
949 /* fill in your code here if you think this call should
950 do anything */
952 p->rng_fault_state = True;
953 return WERR_NOT_SUPPORTED;
956 /*******************************************************************
957 _winreg_ReplaceKey
958 ********************************************************************/
960 WERROR _winreg_ReplaceKey(struct pipes_struct *p,
961 struct winreg_ReplaceKey *r)
963 /* fill in your code here if you think this call should
964 do anything */
966 p->rng_fault_state = True;
967 return WERR_NOT_SUPPORTED;
970 /*******************************************************************
971 _winreg_LoadKey
972 ********************************************************************/
974 WERROR _winreg_LoadKey(struct pipes_struct *p,
975 struct winreg_LoadKey *r)
977 /* fill in your code here if you think this call should
978 do anything */
980 p->rng_fault_state = True;
981 return WERR_NOT_SUPPORTED;
984 /*******************************************************************
985 _winreg_NotifyChangeKeyValue
986 ********************************************************************/
988 WERROR _winreg_NotifyChangeKeyValue(struct pipes_struct *p,
989 struct winreg_NotifyChangeKeyValue *r)
991 return WERR_NOT_SUPPORTED;
994 /*******************************************************************
995 _winreg_QueryMultipleValues
996 ********************************************************************/
998 WERROR _winreg_QueryMultipleValues(struct pipes_struct *p,
999 struct winreg_QueryMultipleValues *r)
1001 struct winreg_QueryMultipleValues2 r2;
1002 uint32_t needed = 0;
1004 r2.in.key_handle = r->in.key_handle;
1005 r2.in.values_in = r->in.values_in;
1006 r2.in.num_values = r->in.num_values;
1007 r2.in.offered = r->in.buffer_size;
1008 r2.in.buffer = r->in.buffer;
1009 r2.out.values_out = r->out.values_out;
1010 r2.out.needed = &needed;
1011 r2.out.buffer = r->out.buffer;
1013 return _winreg_QueryMultipleValues2(p, &r2);
1016 /*******************************************************************
1017 ********************************************************************/
1019 static WERROR construct_multiple_entry(TALLOC_CTX *mem_ctx,
1020 const char *valuename,
1021 uint32_t value_length,
1022 uint32_t offset,
1023 enum winreg_Type type,
1024 struct QueryMultipleValue *r)
1026 r->ve_valuename = talloc_zero(mem_ctx, struct winreg_ValNameBuf);
1027 if (r->ve_valuename == NULL) {
1028 return WERR_NOMEM;
1031 r->ve_valuename->name = talloc_strdup(r->ve_valuename, valuename ? valuename : "");
1032 if (r->ve_valuename->name == NULL) {
1033 return WERR_NOMEM;
1036 r->ve_valuename->size = strlen_m_term(r->ve_valuename->name)*2;
1037 r->ve_valuelen = value_length;
1038 r->ve_valueptr = offset;
1039 r->ve_type = type;
1041 return WERR_OK;
1044 /*******************************************************************
1045 _winreg_QueryMultipleValues2
1046 ********************************************************************/
1048 WERROR _winreg_QueryMultipleValues2(struct pipes_struct *p,
1049 struct winreg_QueryMultipleValues2 *r)
1051 struct registry_key *regkey = find_regkey_by_hnd(p, r->in.key_handle);
1052 struct registry_value *vals = NULL;
1053 const char **names = NULL;
1054 uint32_t offset = 0, num_vals = 0;
1055 DATA_BLOB result = data_blob_null;
1056 int i = 0;
1057 WERROR err = WERR_OK;
1059 if (!regkey) {
1060 return WERR_BADFID;
1063 names = talloc_zero_array(p->mem_ctx, const char *, r->in.num_values);
1064 if (names == NULL) {
1065 return WERR_NOMEM;
1068 for (i=0; i < r->in.num_values; i++) {
1069 if (r->in.values_in[i].ve_valuename &&
1070 r->in.values_in[i].ve_valuename->name) {
1071 names[i] = talloc_strdup(names,
1072 r->in.values_in[i].ve_valuename->name);
1073 if (names[i] == NULL) {
1074 return WERR_NOMEM;
1079 err = reg_querymultiplevalues(p->mem_ctx, regkey,
1080 r->in.num_values, names,
1081 &num_vals, &vals);
1082 if (!W_ERROR_IS_OK(err)) {
1083 return err;
1086 result = data_blob_talloc(p->mem_ctx, NULL, 0);
1088 for (i=0; i < r->in.num_values; i++) {
1089 const char *valuename = NULL;
1091 if (vals[i].data.length > 0) {
1092 if (!data_blob_append(p->mem_ctx, &result,
1093 vals[i].data.data,
1094 vals[i].data.length)) {
1095 return WERR_NOMEM;
1099 if (r->in.values_in[i].ve_valuename &&
1100 r->in.values_in[i].ve_valuename->name) {
1101 valuename = r->in.values_in[i].ve_valuename->name;
1104 err = construct_multiple_entry(r->out.values_out,
1105 valuename,
1106 vals[i].data.length,
1107 offset,
1108 vals[i].type,
1109 &r->out.values_out[i]);
1110 if (!W_ERROR_IS_OK(err)) {
1111 return err;
1114 offset += vals[i].data.length;
1117 *r->out.needed = result.length;
1119 if (r->in.num_values != num_vals) {
1120 return WERR_BADFILE;
1123 if (*r->in.offered >= *r->out.needed) {
1124 if (r->out.buffer) {
1125 memcpy(r->out.buffer, result.data, MIN(result.length, *r->in.offered));
1127 return WERR_OK;
1128 } else {
1129 return WERR_MORE_DATA;
1133 /*******************************************************************
1134 _winreg_DeleteKeyEx
1135 ********************************************************************/
1137 WERROR _winreg_DeleteKeyEx(struct pipes_struct *p,
1138 struct winreg_DeleteKeyEx *r)
1140 /* fill in your code here if you think this call should
1141 do anything */
1143 p->rng_fault_state = True;
1144 return WERR_NOT_SUPPORTED;