tombstones-expunge: Add a test for deleting links to recycled objects
[Samba.git] / source3 / rpc_server / winreg / srv_winreg_nt.c
blobd9ee8d0602d1461f657e144fe0c87346ee100e91
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_FILE_NOT_FOUND;
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_INVALID_HANDLE;
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_INVALID_HANDLE;
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_FILE_NOT_FOUND;
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_INVALID_HANDLE;
255 if (r->in.value_name->name == NULL) {
256 return WERR_INVALID_PARAMETER;
259 if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
260 return WERR_INVALID_PARAMETER;
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_NOT_ENOUGH_MEMORY;
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_NOT_ENOUGH_MEMORY;
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_FILE_NOT_FOUND;
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_FILE_NOT_FOUND;
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_INVALID_HANDLE;
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_INVALID_HANDLE;
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 );
414 char *name;
416 if ( !key )
417 return WERR_INVALID_HANDLE;
419 if ( !r->in.name || !r->in.keyclass )
420 return WERR_INVALID_PARAMETER;
422 DEBUG(8,("_winreg_EnumKey: enumerating key [%s]\n", key->key->name));
424 err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, &name,
425 r->out.last_changed_time);
426 if (!W_ERROR_IS_OK(err)) {
427 return err;
429 r->out.name->name = name;
430 r->out.keyclass->name = "";
431 return WERR_OK;
434 /*****************************************************************************
435 _winreg_EnumValue
436 ****************************************************************************/
438 WERROR _winreg_EnumValue(struct pipes_struct *p,
439 struct winreg_EnumValue *r)
441 WERROR err = WERR_OK;
442 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
443 char *valname = NULL;
444 struct registry_value *val = NULL;
446 if ( !key )
447 return WERR_INVALID_HANDLE;
449 if ( !r->in.name )
450 return WERR_INVALID_PARAMETER;
452 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
453 key->key->name));
455 err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
456 if (!W_ERROR_IS_OK(err)) {
457 return err;
460 if (r->out.name != NULL) {
461 r->out.name->name = valname;
464 if (r->out.type != NULL) {
465 *r->out.type = val->type;
468 if (r->out.value != NULL) {
469 if ((r->out.size == NULL) || (r->out.length == NULL)) {
470 return WERR_INVALID_PARAMETER;
473 if (val->data.length > *r->out.size) {
474 return WERR_MORE_DATA;
477 memcpy( r->out.value, val->data.data, val->data.length );
480 if (r->out.length != NULL) {
481 *r->out.length = val->data.length;
483 if (r->out.size != NULL) {
484 *r->out.size = val->data.length;
487 return WERR_OK;
490 /*******************************************************************
491 _winreg_InitiateSystemShutdown
492 ********************************************************************/
494 WERROR _winreg_InitiateSystemShutdown(struct pipes_struct *p,
495 struct winreg_InitiateSystemShutdown *r)
497 struct winreg_InitiateSystemShutdownEx s;
499 s.in.hostname = r->in.hostname;
500 s.in.message = r->in.message;
501 s.in.timeout = r->in.timeout;
502 s.in.force_apps = r->in.force_apps;
503 s.in.do_reboot = r->in.do_reboot;
504 s.in.reason = 0;
506 /* thunk down to _winreg_InitiateSystemShutdownEx()
507 (just returns a status) */
509 return _winreg_InitiateSystemShutdownEx( p, &s );
512 /*******************************************************************
513 _winreg_InitiateSystemShutdownEx
514 ********************************************************************/
516 #define SHUTDOWN_R_STRING "-r"
517 #define SHUTDOWN_F_STRING "-f"
520 WERROR _winreg_InitiateSystemShutdownEx(struct pipes_struct *p,
521 struct winreg_InitiateSystemShutdownEx *r)
523 char *shutdown_script = NULL;
524 char *msg = NULL;
525 char *chkmsg = NULL;
526 fstring str_timeout;
527 fstring str_reason;
528 fstring do_reboot;
529 fstring f;
530 int ret = -1;
531 bool can_shutdown = false;
533 shutdown_script = lp_shutdown_script(p->mem_ctx);
534 if (!shutdown_script) {
535 return WERR_NOT_ENOUGH_MEMORY;
537 if (!*shutdown_script) {
538 return WERR_ACCESS_DENIED;
541 /* pull the message string and perform necessary sanity checks on it */
543 if ( r->in.message && r->in.message->string ) {
544 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
545 return WERR_NOT_ENOUGH_MEMORY;
547 chkmsg = talloc_array(p->mem_ctx, char, strlen(msg)+1);
548 if (!chkmsg) {
549 return WERR_NOT_ENOUGH_MEMORY;
551 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
554 fstr_sprintf(str_timeout, "%d", r->in.timeout);
555 fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
556 fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
557 fstr_sprintf(str_reason, "%d", r->in.reason );
559 shutdown_script = talloc_all_string_sub(p->mem_ctx,
560 shutdown_script, "%z", chkmsg ? chkmsg : "");
561 if (!shutdown_script) {
562 return WERR_NOT_ENOUGH_MEMORY;
564 shutdown_script = talloc_all_string_sub(p->mem_ctx,
565 shutdown_script, "%t", str_timeout);
566 if (!shutdown_script) {
567 return WERR_NOT_ENOUGH_MEMORY;
569 shutdown_script = talloc_all_string_sub(p->mem_ctx,
570 shutdown_script, "%r", do_reboot);
571 if (!shutdown_script) {
572 return WERR_NOT_ENOUGH_MEMORY;
574 shutdown_script = talloc_all_string_sub(p->mem_ctx,
575 shutdown_script, "%f", f);
576 if (!shutdown_script) {
577 return WERR_NOT_ENOUGH_MEMORY;
579 shutdown_script = talloc_all_string_sub(p->mem_ctx,
580 shutdown_script, "%x", str_reason);
581 if (!shutdown_script) {
582 return WERR_NOT_ENOUGH_MEMORY;
585 can_shutdown = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
587 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
588 Take the error return from the script and provide it as the Windows return code. */
590 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
592 if ( can_shutdown )
593 become_root();
595 ret = smbrun(shutdown_script, NULL, NULL);
597 if ( can_shutdown )
598 unbecome_root();
600 /********** END SeRemoteShutdownPrivilege BLOCK **********/
602 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
603 shutdown_script, ret));
605 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
608 /*******************************************************************
609 _winreg_AbortSystemShutdown
610 ********************************************************************/
612 WERROR _winreg_AbortSystemShutdown(struct pipes_struct *p,
613 struct winreg_AbortSystemShutdown *r)
615 const char *abort_shutdown_script = lp_abort_shutdown_script(talloc_tos());
616 int ret = -1;
617 bool can_shutdown = false;
619 if (!*abort_shutdown_script)
620 return WERR_ACCESS_DENIED;
622 can_shutdown = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
624 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
626 if ( can_shutdown )
627 become_root();
629 ret = smbrun(abort_shutdown_script, NULL, NULL);
631 if ( can_shutdown )
632 unbecome_root();
634 /********** END SeRemoteShutdownPrivilege BLOCK **********/
636 DEBUG(3,("_winreg_AbortSystemShutdown: Running the command `%s' gave %d\n",
637 abort_shutdown_script, ret));
639 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
642 /*******************************************************************
643 ********************************************************************/
645 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
647 char *p = NULL;
648 int num_services = lp_numservices();
649 int snum = -1;
650 const char *share_path = NULL;
651 char *fname = *pp_fname;
653 /* convert to a unix path, stripping the C:\ along the way */
655 if (!(p = valid_share_pathname(ctx, fname))) {
656 return -1;
659 /* has to exist within a valid file share */
661 for (snum=0; snum<num_services; snum++) {
662 if (!lp_snum_ok(snum) || lp_printable(snum)) {
663 continue;
666 share_path = lp_path(talloc_tos(), snum);
668 /* make sure we have a path (e.g. [homes] ) */
669 if (strlen(share_path) == 0) {
670 continue;
673 if (strncmp(share_path, p, strlen(share_path)) == 0) {
674 break;
678 *pp_fname = p;
679 return (snum < num_services) ? snum : -1;
682 /*******************************************************************
683 _winreg_RestoreKey
684 ********************************************************************/
686 WERROR _winreg_RestoreKey(struct pipes_struct *p,
687 struct winreg_RestoreKey *r)
689 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
690 char *fname = NULL;
691 int snum = -1;
693 if ( !regkey )
694 return WERR_INVALID_HANDLE;
696 if ( !r->in.filename || !r->in.filename->name )
697 return WERR_INVALID_PARAMETER;
699 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
700 if (!fname) {
701 return WERR_NOT_ENOUGH_MEMORY;
704 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
705 "\"%s\"\n", regkey->key->name, fname));
707 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
708 return WERR_BAD_PATHNAME;
710 /* user must posses SeRestorePrivilege for this this proceed */
712 if ( !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_RESTORE)) {
713 return WERR_ACCESS_DENIED;
716 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
717 regkey->key->name, fname, lp_servicename(talloc_tos(), snum) ));
719 return reg_restorekey(regkey, fname);
722 /*******************************************************************
723 _winreg_SaveKey
724 ********************************************************************/
726 WERROR _winreg_SaveKey(struct pipes_struct *p,
727 struct winreg_SaveKey *r)
729 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
730 char *fname = NULL;
731 int snum = -1;
733 if ( !regkey )
734 return WERR_INVALID_HANDLE;
736 if ( !r->in.filename || !r->in.filename->name )
737 return WERR_INVALID_PARAMETER;
739 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
740 if (!fname) {
741 return WERR_NOT_ENOUGH_MEMORY;
744 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
745 regkey->key->name, fname));
747 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
748 return WERR_BAD_PATHNAME;
750 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
751 regkey->key->name, fname, lp_servicename(talloc_tos(), snum) ));
753 return reg_savekey(regkey, fname);
756 /*******************************************************************
757 _winreg_SaveKeyEx
758 ********************************************************************/
760 WERROR _winreg_SaveKeyEx(struct pipes_struct *p,
761 struct winreg_SaveKeyEx *r)
763 /* fill in your code here if you think this call should
764 do anything */
766 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
767 return WERR_NOT_SUPPORTED;
770 /*******************************************************************
771 _winreg_CreateKey
772 ********************************************************************/
774 WERROR _winreg_CreateKey(struct pipes_struct *p,
775 struct winreg_CreateKey *r)
777 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
778 struct registry_key *new_key = NULL;
779 WERROR result = WERR_OK;
781 if ( !parent )
782 return WERR_INVALID_HANDLE;
784 DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
785 "subkey name '%s'\n", parent->key->name, r->in.name.name));
787 result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
788 &new_key, r->out.action_taken);
789 if (!W_ERROR_IS_OK(result)) {
790 return result;
793 if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
794 TALLOC_FREE(new_key);
795 return WERR_FILE_NOT_FOUND;
798 return WERR_OK;
801 /*******************************************************************
802 _winreg_SetValue
803 ********************************************************************/
805 WERROR _winreg_SetValue(struct pipes_struct *p,
806 struct winreg_SetValue *r)
808 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
809 struct registry_value *val = NULL;
811 if ( !key )
812 return WERR_INVALID_HANDLE;
814 DEBUG(8,("_winreg_SetValue: Setting value for [%s:%s]\n",
815 key->key->name, r->in.name.name));
817 val = talloc_zero(p->mem_ctx, struct registry_value);
818 if (val == NULL) {
819 return WERR_NOT_ENOUGH_MEMORY;
822 val->type = r->in.type;
823 val->data = data_blob_talloc(p->mem_ctx, r->in.data, r->in.size);
825 return reg_setvalue(key, r->in.name.name, val);
828 /*******************************************************************
829 _winreg_DeleteKey
830 ********************************************************************/
832 WERROR _winreg_DeleteKey(struct pipes_struct *p,
833 struct winreg_DeleteKey *r)
835 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
837 if ( !parent )
838 return WERR_INVALID_HANDLE;
840 return reg_deletekey(parent, r->in.key.name);
844 /*******************************************************************
845 _winreg_DeleteValue
846 ********************************************************************/
848 WERROR _winreg_DeleteValue(struct pipes_struct *p,
849 struct winreg_DeleteValue *r)
851 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
853 if ( !key )
854 return WERR_INVALID_HANDLE;
856 return reg_deletevalue(key, r->in.value.name);
859 /*******************************************************************
860 _winreg_GetKeySecurity
861 ********************************************************************/
863 WERROR _winreg_GetKeySecurity(struct pipes_struct *p,
864 struct winreg_GetKeySecurity *r)
866 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
867 WERROR err = WERR_OK;
868 struct security_descriptor *secdesc = NULL;
869 uint8_t *data = NULL;
870 size_t len = 0;
872 if ( !key )
873 return WERR_INVALID_HANDLE;
875 /* access checks first */
877 if ( !(key->key->access_granted & SEC_STD_READ_CONTROL) )
878 return WERR_ACCESS_DENIED;
880 err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
881 if (!W_ERROR_IS_OK(err)) {
882 return err;
885 err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
886 &data, &len));
887 if (!W_ERROR_IS_OK(err)) {
888 return err;
891 if (len > r->out.sd->size) {
892 r->out.sd->size = len;
893 return WERR_INSUFFICIENT_BUFFER;
896 r->out.sd->size = len;
897 r->out.sd->len = len;
898 r->out.sd->data = data;
900 return WERR_OK;
903 /*******************************************************************
904 _winreg_SetKeySecurity
905 ********************************************************************/
907 WERROR _winreg_SetKeySecurity(struct pipes_struct *p,
908 struct winreg_SetKeySecurity *r)
910 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
911 struct security_descriptor *secdesc = NULL;
912 WERROR err = WERR_OK;
914 if ( !key )
915 return WERR_INVALID_HANDLE;
917 /* access checks first */
919 if ( !(key->key->access_granted & SEC_STD_WRITE_DAC) )
920 return WERR_ACCESS_DENIED;
922 err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
923 r->in.sd->len, &secdesc));
924 if (!W_ERROR_IS_OK(err)) {
925 return err;
928 return reg_setkeysecurity(key, secdesc);
931 /*******************************************************************
932 _winreg_FlushKey
933 ********************************************************************/
935 WERROR _winreg_FlushKey(struct pipes_struct *p,
936 struct winreg_FlushKey *r)
938 /* I'm just replying OK because there's not a lot
939 here I see to do i --jerry */
941 return WERR_OK;
944 /*******************************************************************
945 _winreg_UnLoadKey
946 ********************************************************************/
948 WERROR _winreg_UnLoadKey(struct pipes_struct *p,
949 struct winreg_UnLoadKey *r)
951 /* fill in your code here if you think this call should
952 do anything */
954 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
955 return WERR_NOT_SUPPORTED;
958 /*******************************************************************
959 _winreg_ReplaceKey
960 ********************************************************************/
962 WERROR _winreg_ReplaceKey(struct pipes_struct *p,
963 struct winreg_ReplaceKey *r)
965 /* fill in your code here if you think this call should
966 do anything */
968 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
969 return WERR_NOT_SUPPORTED;
972 /*******************************************************************
973 _winreg_LoadKey
974 ********************************************************************/
976 WERROR _winreg_LoadKey(struct pipes_struct *p,
977 struct winreg_LoadKey *r)
979 /* fill in your code here if you think this call should
980 do anything */
982 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
983 return WERR_NOT_SUPPORTED;
986 /*******************************************************************
987 _winreg_NotifyChangeKeyValue
988 ********************************************************************/
990 WERROR _winreg_NotifyChangeKeyValue(struct pipes_struct *p,
991 struct winreg_NotifyChangeKeyValue *r)
993 return WERR_NOT_SUPPORTED;
996 /*******************************************************************
997 _winreg_QueryMultipleValues
998 ********************************************************************/
1000 WERROR _winreg_QueryMultipleValues(struct pipes_struct *p,
1001 struct winreg_QueryMultipleValues *r)
1003 struct winreg_QueryMultipleValues2 r2;
1004 uint32_t needed = 0;
1006 r2.in.key_handle = r->in.key_handle;
1007 r2.in.values_in = r->in.values_in;
1008 r2.in.num_values = r->in.num_values;
1009 r2.in.offered = r->in.buffer_size;
1010 r2.in.buffer = r->in.buffer;
1011 r2.out.values_out = r->out.values_out;
1012 r2.out.needed = &needed;
1013 r2.out.buffer = r->out.buffer;
1015 return _winreg_QueryMultipleValues2(p, &r2);
1018 /*******************************************************************
1019 ********************************************************************/
1021 static WERROR construct_multiple_entry(TALLOC_CTX *mem_ctx,
1022 const char *valuename,
1023 uint32_t value_length,
1024 uint32_t offset,
1025 enum winreg_Type type,
1026 struct QueryMultipleValue *r)
1028 r->ve_valuename = talloc_zero(mem_ctx, struct winreg_ValNameBuf);
1029 if (r->ve_valuename == NULL) {
1030 return WERR_NOT_ENOUGH_MEMORY;
1033 r->ve_valuename->name = talloc_strdup(r->ve_valuename, valuename ? valuename : "");
1034 if (r->ve_valuename->name == NULL) {
1035 return WERR_NOT_ENOUGH_MEMORY;
1038 r->ve_valuename->size = strlen_m_term(r->ve_valuename->name)*2;
1039 r->ve_valuelen = value_length;
1040 r->ve_valueptr = offset;
1041 r->ve_type = type;
1043 return WERR_OK;
1046 /*******************************************************************
1047 _winreg_QueryMultipleValues2
1048 ********************************************************************/
1050 WERROR _winreg_QueryMultipleValues2(struct pipes_struct *p,
1051 struct winreg_QueryMultipleValues2 *r)
1053 struct registry_key *regkey = find_regkey_by_hnd(p, r->in.key_handle);
1054 struct registry_value *vals = NULL;
1055 const char **names = NULL;
1056 uint32_t offset = 0, num_vals = 0;
1057 DATA_BLOB result = data_blob_null;
1058 int i = 0;
1059 WERROR err = WERR_OK;
1061 if (!regkey) {
1062 return WERR_INVALID_HANDLE;
1065 names = talloc_zero_array(p->mem_ctx, const char *, r->in.num_values);
1066 if (names == NULL) {
1067 return WERR_NOT_ENOUGH_MEMORY;
1070 for (i=0; i < r->in.num_values; i++) {
1071 if (r->in.values_in[i].ve_valuename &&
1072 r->in.values_in[i].ve_valuename->name) {
1073 names[i] = talloc_strdup(names,
1074 r->in.values_in[i].ve_valuename->name);
1075 if (names[i] == NULL) {
1076 return WERR_NOT_ENOUGH_MEMORY;
1081 err = reg_querymultiplevalues(p->mem_ctx, regkey,
1082 r->in.num_values, names,
1083 &num_vals, &vals);
1084 if (!W_ERROR_IS_OK(err)) {
1085 return err;
1088 result = data_blob_talloc(p->mem_ctx, NULL, 0);
1090 for (i=0; i < r->in.num_values; i++) {
1091 const char *valuename = NULL;
1093 if (vals[i].data.length > 0) {
1094 if (!data_blob_append(p->mem_ctx, &result,
1095 vals[i].data.data,
1096 vals[i].data.length)) {
1097 return WERR_NOT_ENOUGH_MEMORY;
1101 if (r->in.values_in[i].ve_valuename &&
1102 r->in.values_in[i].ve_valuename->name) {
1103 valuename = r->in.values_in[i].ve_valuename->name;
1106 err = construct_multiple_entry(r->out.values_out,
1107 valuename,
1108 vals[i].data.length,
1109 offset,
1110 vals[i].type,
1111 &r->out.values_out[i]);
1112 if (!W_ERROR_IS_OK(err)) {
1113 return err;
1116 offset += vals[i].data.length;
1119 *r->out.needed = result.length;
1121 if (r->in.num_values != num_vals) {
1122 return WERR_FILE_NOT_FOUND;
1125 if (*r->in.offered >= *r->out.needed) {
1126 if (r->out.buffer) {
1127 memcpy(r->out.buffer, result.data, MIN(result.length, *r->in.offered));
1129 return WERR_OK;
1130 } else {
1131 return WERR_MORE_DATA;
1135 /*******************************************************************
1136 _winreg_DeleteKeyEx
1137 ********************************************************************/
1139 WERROR _winreg_DeleteKeyEx(struct pipes_struct *p,
1140 struct winreg_DeleteKeyEx *r)
1142 /* fill in your code here if you think this call should
1143 do anything */
1145 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1146 return WERR_NOT_SUPPORTED;