s3: use monotonic clock for time deltas in namequery functions
[Samba/ita.git] / source3 / rpc_server / srv_winreg_nt.c
blobde15f9f82f0728bbe78eae6d67c65b94c54aea05
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"
28 #include "rpc_misc.h"
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_RPC_SRV
33 /******************************************************************
34 Find a registry key handle and return a struct registry_key *
35 *****************************************************************/
37 static struct registry_key *find_regkey_by_hnd(struct pipes_struct *p,
38 struct policy_handle *hnd)
40 struct registry_key *regkey = NULL;
42 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) {
43 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
44 return NULL;
47 return regkey;
50 /*******************************************************************
51 Function for open a new registry handle and creating a handle
52 Note that P should be valid & hnd should already have space
54 When we open a key, we store the full path to the key as
55 HK[LM|U]\<key>\<key>\...
56 *******************************************************************/
58 static WERROR open_registry_key(struct pipes_struct *p,
59 struct policy_handle *hnd,
60 struct registry_key *parent,
61 const char *subkeyname,
62 uint32_t access_desired)
64 WERROR result = WERR_OK;
65 struct registry_key *key;
67 if (parent == NULL) {
68 result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
69 p->server_info->ptok, &key);
71 else {
72 result = reg_openkey(p->mem_ctx, parent, subkeyname,
73 access_desired, &key);
76 if ( !W_ERROR_IS_OK(result) ) {
77 return result;
80 if ( !create_policy_hnd( p, hnd, key ) ) {
81 return WERR_BADFILE;
84 return WERR_OK;
87 /*******************************************************************
88 Function for open a new registry handle and creating a handle
89 Note that P should be valid & hnd should already have space
90 *******************************************************************/
92 static bool close_registry_key(struct pipes_struct *p,
93 struct policy_handle *hnd)
95 struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
97 if ( !regkey ) {
98 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
99 OUR_HANDLE(hnd)));
100 return False;
103 close_policy_hnd(p, hnd);
105 return True;
108 /********************************************************************
109 _winreg_CloseKey
110 ********************************************************************/
112 WERROR _winreg_CloseKey(struct pipes_struct *p,
113 struct winreg_CloseKey *r)
115 /* close the policy handle */
117 if (!close_registry_key(p, r->in.handle))
118 return WERR_BADFID;
120 ZERO_STRUCTP(r->out.handle);
122 return WERR_OK;
125 /*******************************************************************
126 _winreg_OpenHKLM
127 ********************************************************************/
129 WERROR _winreg_OpenHKLM(struct pipes_struct *p,
130 struct winreg_OpenHKLM *r)
132 return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
135 /*******************************************************************
136 _winreg_OpenHKPD
137 ********************************************************************/
139 WERROR _winreg_OpenHKPD(struct pipes_struct *p,
140 struct winreg_OpenHKPD *r)
142 return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
145 /*******************************************************************
146 _winreg_OpenHKPT
147 ********************************************************************/
149 WERROR _winreg_OpenHKPT(struct pipes_struct *p,
150 struct winreg_OpenHKPT *r)
152 return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
155 /*******************************************************************
156 _winreg_OpenHKCR
157 ********************************************************************/
159 WERROR _winreg_OpenHKCR(struct pipes_struct *p,
160 struct winreg_OpenHKCR *r)
162 return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
165 /*******************************************************************
166 _winreg_OpenHKU
167 ********************************************************************/
169 WERROR _winreg_OpenHKU(struct pipes_struct *p,
170 struct winreg_OpenHKU *r)
172 return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
175 /*******************************************************************
176 _winreg_OpenHKCU
177 ********************************************************************/
179 WERROR _winreg_OpenHKCU(struct pipes_struct *p,
180 struct winreg_OpenHKCU *r)
182 return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
185 /*******************************************************************
186 _winreg_OpenHKCC
187 ********************************************************************/
189 WERROR _winreg_OpenHKCC(struct pipes_struct *p,
190 struct winreg_OpenHKCC *r)
192 return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
195 /*******************************************************************
196 _winreg_OpenHKDD
197 ********************************************************************/
199 WERROR _winreg_OpenHKDD(struct pipes_struct *p,
200 struct winreg_OpenHKDD *r)
202 return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
205 /*******************************************************************
206 _winreg_OpenHKPN
207 ********************************************************************/
209 WERROR _winreg_OpenHKPN(struct pipes_struct *p,
210 struct winreg_OpenHKPN *r)
212 return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
215 /*******************************************************************
216 _winreg_OpenKey
217 ********************************************************************/
219 WERROR _winreg_OpenKey(struct pipes_struct *p,
220 struct winreg_OpenKey *r)
222 struct registry_key *parent = find_regkey_by_hnd(p, r->in.parent_handle );
224 if ( !parent )
225 return WERR_BADFID;
227 return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
230 /*******************************************************************
231 _winreg_QueryValue
232 ********************************************************************/
234 WERROR _winreg_QueryValue(struct pipes_struct *p,
235 struct winreg_QueryValue *r)
237 WERROR status = WERR_BADFILE;
238 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
239 prs_struct prs_hkpd;
241 uint8_t *outbuf = NULL;
242 uint32_t outbuf_size = 0;
244 bool free_buf = False;
245 bool free_prs = False;
247 if ( !regkey )
248 return WERR_BADFID;
250 if (r->in.value_name->name == NULL) {
251 return WERR_INVALID_PARAM;
254 if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
255 return WERR_INVALID_PARAM;
258 DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
259 DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
261 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
262 if(regkey->key->type == REG_KEY_HKPD)
264 if (strequal(r->in.value_name->name, "Global")) {
265 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
266 return WERR_NOMEM;
267 status = reg_perfcount_get_hkpd(
268 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
269 outbuf = (uint8_t *)prs_hkpd.data_p;
270 free_prs = True;
272 else if (strequal(r->in.value_name->name, "Counter 009")) {
273 outbuf_size = reg_perfcount_get_counter_names(
274 reg_perfcount_get_base_index(),
275 (char **)(void *)&outbuf);
276 free_buf = True;
278 else if (strequal(r->in.value_name->name, "Explain 009")) {
279 outbuf_size = reg_perfcount_get_counter_help(
280 reg_perfcount_get_base_index(),
281 (char **)(void *)&outbuf);
282 free_buf = True;
284 else if (isdigit(r->in.value_name->name[0])) {
285 /* we probably have a request for a specific object
286 * here */
287 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
288 return WERR_NOMEM;
289 status = reg_perfcount_get_hkpd(
290 &prs_hkpd, *r->in.data_size, &outbuf_size,
291 r->in.value_name->name);
292 outbuf = (uint8_t *)prs_hkpd.data_p;
293 free_prs = True;
295 else {
296 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
297 r->in.value_name->name));
298 return WERR_BADFILE;
301 *r->out.type = REG_BINARY;
303 else {
304 struct registry_value *val;
306 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
307 &val);
308 if (!W_ERROR_IS_OK(status)) {
310 DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
311 win_errstr(status)));
313 if (r->out.data_size) {
314 *r->out.data_size = 0;
316 if (r->out.data_length) {
317 *r->out.data_length = 0;
319 return status;
322 outbuf = val->data.data;
323 outbuf_size = val->data.length;
324 *r->out.type = val->type;
327 status = WERR_BADFILE;
329 if (*r->in.data_size < outbuf_size) {
330 *r->out.data_size = outbuf_size;
331 status = r->in.data ? WERR_MORE_DATA : WERR_OK;
332 } else {
333 *r->out.data_length = outbuf_size;
334 *r->out.data_size = outbuf_size;
335 if (r->out.data) {
336 memcpy(r->out.data, outbuf, outbuf_size);
338 status = WERR_OK;
341 if (free_prs) prs_mem_free(&prs_hkpd);
342 if (free_buf) SAFE_FREE(outbuf);
344 return status;
347 /*****************************************************************************
348 _winreg_QueryInfoKey
349 ****************************************************************************/
351 WERROR _winreg_QueryInfoKey(struct pipes_struct *p,
352 struct winreg_QueryInfoKey *r)
354 WERROR status = WERR_OK;
355 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
357 if ( !regkey )
358 return WERR_BADFID;
360 r->out.classname->name = NULL;
362 status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
363 r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
364 r->out.max_valbufsize, r->out.secdescsize,
365 r->out.last_changed_time);
366 if (!W_ERROR_IS_OK(status)) {
367 return status;
371 * These calculations account for the registry buffers being
372 * UTF-16. They are inexact at best, but so far they worked.
375 *r->out.max_subkeylen *= 2;
377 *r->out.max_valnamelen += 1;
378 *r->out.max_valnamelen *= 2;
380 return WERR_OK;
384 /*****************************************************************************
385 _winreg_GetVersion
386 ****************************************************************************/
388 WERROR _winreg_GetVersion(struct pipes_struct *p,
389 struct winreg_GetVersion *r)
391 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
393 if ( !regkey )
394 return WERR_BADFID;
396 return reg_getversion(r->out.version);
400 /*****************************************************************************
401 _winreg_EnumKey
402 ****************************************************************************/
404 WERROR _winreg_EnumKey(struct pipes_struct *p,
405 struct winreg_EnumKey *r)
407 WERROR err = WERR_OK;
408 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
410 if ( !key )
411 return WERR_BADFID;
413 if ( !r->in.name || !r->in.keyclass )
414 return WERR_INVALID_PARAM;
416 DEBUG(8,("_winreg_EnumKey: enumerating key [%s]\n", key->key->name));
418 err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, (char **)&r->out.name->name,
419 r->out.last_changed_time);
420 if (!W_ERROR_IS_OK(err)) {
421 return err;
423 r->out.keyclass->name = "";
424 return WERR_OK;
427 /*****************************************************************************
428 _winreg_EnumValue
429 ****************************************************************************/
431 WERROR _winreg_EnumValue(struct pipes_struct *p,
432 struct winreg_EnumValue *r)
434 WERROR err = WERR_OK;
435 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
436 char *valname = NULL;
437 struct registry_value *val = NULL;
439 if ( !key )
440 return WERR_BADFID;
442 if ( !r->in.name )
443 return WERR_INVALID_PARAM;
445 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
446 key->key->name));
448 err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
449 if (!W_ERROR_IS_OK(err)) {
450 return err;
453 if (r->out.name != NULL) {
454 r->out.name->name = valname;
457 if (r->out.type != NULL) {
458 *r->out.type = val->type;
461 if (r->out.value != NULL) {
462 if ((r->out.size == NULL) || (r->out.length == NULL)) {
463 return WERR_INVALID_PARAM;
466 if (val->data.length > *r->out.size) {
467 return WERR_MORE_DATA;
470 memcpy( r->out.value, val->data.data, val->data.length );
473 if (r->out.length != NULL) {
474 *r->out.length = val->data.length;
476 if (r->out.size != NULL) {
477 *r->out.size = val->data.length;
480 return WERR_OK;
483 /*******************************************************************
484 _winreg_InitiateSystemShutdown
485 ********************************************************************/
487 WERROR _winreg_InitiateSystemShutdown(struct pipes_struct *p,
488 struct winreg_InitiateSystemShutdown *r)
490 struct winreg_InitiateSystemShutdownEx s;
492 s.in.hostname = r->in.hostname;
493 s.in.message = r->in.message;
494 s.in.timeout = r->in.timeout;
495 s.in.force_apps = r->in.force_apps;
496 s.in.do_reboot = r->in.do_reboot;
497 s.in.reason = 0;
499 /* thunk down to _winreg_InitiateSystemShutdownEx()
500 (just returns a status) */
502 return _winreg_InitiateSystemShutdownEx( p, &s );
505 /*******************************************************************
506 _winreg_InitiateSystemShutdownEx
507 ********************************************************************/
509 #define SHUTDOWN_R_STRING "-r"
510 #define SHUTDOWN_F_STRING "-f"
513 WERROR _winreg_InitiateSystemShutdownEx(struct pipes_struct *p,
514 struct winreg_InitiateSystemShutdownEx *r)
516 char *shutdown_script = NULL;
517 char *msg = NULL;
518 char *chkmsg = NULL;
519 fstring str_timeout;
520 fstring str_reason;
521 fstring do_reboot;
522 fstring f;
523 int ret = -1;
524 bool can_shutdown = false;
526 shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
527 if (!shutdown_script) {
528 return WERR_NOMEM;
530 if (!*shutdown_script) {
531 return WERR_ACCESS_DENIED;
534 /* pull the message string and perform necessary sanity checks on it */
536 if ( r->in.message && r->in.message->string ) {
537 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
538 return WERR_NOMEM;
540 chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
541 if (!chkmsg) {
542 return WERR_NOMEM;
544 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
547 fstr_sprintf(str_timeout, "%d", r->in.timeout);
548 fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
549 fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
550 fstr_sprintf(str_reason, "%d", r->in.reason );
552 shutdown_script = talloc_all_string_sub(p->mem_ctx,
553 shutdown_script, "%z", chkmsg ? chkmsg : "");
554 if (!shutdown_script) {
555 return WERR_NOMEM;
557 shutdown_script = talloc_all_string_sub(p->mem_ctx,
558 shutdown_script, "%t", str_timeout);
559 if (!shutdown_script) {
560 return WERR_NOMEM;
562 shutdown_script = talloc_all_string_sub(p->mem_ctx,
563 shutdown_script, "%r", do_reboot);
564 if (!shutdown_script) {
565 return WERR_NOMEM;
567 shutdown_script = talloc_all_string_sub(p->mem_ctx,
568 shutdown_script, "%f", f);
569 if (!shutdown_script) {
570 return WERR_NOMEM;
572 shutdown_script = talloc_all_string_sub(p->mem_ctx,
573 shutdown_script, "%x", str_reason);
574 if (!shutdown_script) {
575 return WERR_NOMEM;
578 can_shutdown = user_has_privileges( p->server_info->ptok,
579 &se_remote_shutdown );
581 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
582 Take the error return from the script and provide it as the Windows return code. */
584 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
586 if ( can_shutdown )
587 become_root();
589 ret = smbrun( shutdown_script, NULL );
591 if ( can_shutdown )
592 unbecome_root();
594 /********** END SeRemoteShutdownPrivilege BLOCK **********/
596 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
597 shutdown_script, ret));
599 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
602 /*******************************************************************
603 _winreg_AbortSystemShutdown
604 ********************************************************************/
606 WERROR _winreg_AbortSystemShutdown(struct pipes_struct *p,
607 struct winreg_AbortSystemShutdown *r)
609 const char *abort_shutdown_script = lp_abort_shutdown_script();
610 int ret = -1;
611 bool can_shutdown = false;
613 if (!*abort_shutdown_script)
614 return WERR_ACCESS_DENIED;
616 can_shutdown = user_has_privileges( p->server_info->ptok,
617 &se_remote_shutdown );
619 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
621 if ( can_shutdown )
622 become_root();
624 ret = smbrun( abort_shutdown_script, NULL );
626 if ( can_shutdown )
627 unbecome_root();
629 /********** END SeRemoteShutdownPrivilege BLOCK **********/
631 DEBUG(3,("_winreg_AbortSystemShutdown: Running the command `%s' gave %d\n",
632 abort_shutdown_script, ret));
634 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
637 /*******************************************************************
638 ********************************************************************/
640 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
642 char *p = NULL;
643 int num_services = lp_numservices();
644 int snum = -1;
645 const char *share_path = NULL;
646 char *fname = *pp_fname;
648 /* convert to a unix path, stripping the C:\ along the way */
650 if (!(p = valid_share_pathname(ctx, fname))) {
651 return -1;
654 /* has to exist within a valid file share */
656 for (snum=0; snum<num_services; snum++) {
657 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
658 continue;
661 share_path = lp_pathname(snum);
663 /* make sure we have a path (e.g. [homes] ) */
664 if (strlen(share_path) == 0) {
665 continue;
668 if (strncmp(share_path, p, strlen(share_path)) == 0) {
669 break;
673 *pp_fname = p;
674 return (snum < num_services) ? snum : -1;
677 /*******************************************************************
678 _winreg_RestoreKey
679 ********************************************************************/
681 WERROR _winreg_RestoreKey(struct pipes_struct *p,
682 struct winreg_RestoreKey *r)
684 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
685 char *fname = NULL;
686 int snum = -1;
688 if ( !regkey )
689 return WERR_BADFID;
691 if ( !r->in.filename || !r->in.filename->name )
692 return WERR_INVALID_PARAM;
694 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
695 if (!fname) {
696 return WERR_NOMEM;
699 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
700 "\"%s\"\n", regkey->key->name, fname));
702 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
703 return WERR_OBJECT_PATH_INVALID;
705 /* user must posses SeRestorePrivilege for this this proceed */
707 if ( !user_has_privileges( p->server_info->ptok, &se_restore ) )
708 return WERR_ACCESS_DENIED;
710 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
711 regkey->key->name, fname, lp_servicename(snum) ));
713 return reg_restorekey(regkey, fname);
716 /*******************************************************************
717 _winreg_SaveKey
718 ********************************************************************/
720 WERROR _winreg_SaveKey(struct pipes_struct *p,
721 struct winreg_SaveKey *r)
723 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
724 char *fname = NULL;
725 int snum = -1;
727 if ( !regkey )
728 return WERR_BADFID;
730 if ( !r->in.filename || !r->in.filename->name )
731 return WERR_INVALID_PARAM;
733 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
734 if (!fname) {
735 return WERR_NOMEM;
738 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
739 regkey->key->name, fname));
741 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
742 return WERR_OBJECT_PATH_INVALID;
744 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
745 regkey->key->name, fname, lp_servicename(snum) ));
747 return reg_savekey(regkey, fname);
750 /*******************************************************************
751 _winreg_SaveKeyEx
752 ********************************************************************/
754 WERROR _winreg_SaveKeyEx(struct pipes_struct *p,
755 struct winreg_SaveKeyEx *r)
757 /* fill in your code here if you think this call should
758 do anything */
760 p->rng_fault_state = True;
761 return WERR_NOT_SUPPORTED;
764 /*******************************************************************
765 _winreg_CreateKey
766 ********************************************************************/
768 WERROR _winreg_CreateKey(struct pipes_struct *p,
769 struct winreg_CreateKey *r)
771 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
772 struct registry_key *new_key = NULL;
773 WERROR result = WERR_OK;
775 if ( !parent )
776 return WERR_BADFID;
778 DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
779 "subkey name '%s'\n", parent->key->name, r->in.name.name));
781 result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
782 &new_key, r->out.action_taken);
783 if (!W_ERROR_IS_OK(result)) {
784 return result;
787 if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
788 TALLOC_FREE(new_key);
789 return WERR_BADFILE;
792 return WERR_OK;
795 /*******************************************************************
796 _winreg_SetValue
797 ********************************************************************/
799 WERROR _winreg_SetValue(struct pipes_struct *p,
800 struct winreg_SetValue *r)
802 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
803 struct registry_value *val = NULL;
805 if ( !key )
806 return WERR_BADFID;
808 DEBUG(8,("_winreg_SetValue: Setting value for [%s:%s]\n",
809 key->key->name, r->in.name.name));
811 val = talloc_zero(p->mem_ctx, struct registry_value);
812 if (val == NULL) {
813 return WERR_NOMEM;
816 val->type = r->in.type;
817 val->data = data_blob_talloc(p->mem_ctx, r->in.data, r->in.size);
819 return reg_setvalue(key, r->in.name.name, val);
822 /*******************************************************************
823 _winreg_DeleteKey
824 ********************************************************************/
826 WERROR _winreg_DeleteKey(struct pipes_struct *p,
827 struct winreg_DeleteKey *r)
829 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
831 if ( !parent )
832 return WERR_BADFID;
834 return reg_deletekey(parent, r->in.key.name);
838 /*******************************************************************
839 _winreg_DeleteValue
840 ********************************************************************/
842 WERROR _winreg_DeleteValue(struct pipes_struct *p,
843 struct winreg_DeleteValue *r)
845 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
847 if ( !key )
848 return WERR_BADFID;
850 return reg_deletevalue(key, r->in.value.name);
853 /*******************************************************************
854 _winreg_GetKeySecurity
855 ********************************************************************/
857 WERROR _winreg_GetKeySecurity(struct pipes_struct *p,
858 struct winreg_GetKeySecurity *r)
860 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
861 WERROR err = WERR_OK;
862 struct security_descriptor *secdesc = NULL;
863 uint8 *data = NULL;
864 size_t len = 0;
866 if ( !key )
867 return WERR_BADFID;
869 /* access checks first */
871 if ( !(key->key->access_granted & SEC_STD_READ_CONTROL) )
872 return WERR_ACCESS_DENIED;
874 err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
875 if (!W_ERROR_IS_OK(err)) {
876 return err;
879 err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
880 &data, &len));
881 if (!W_ERROR_IS_OK(err)) {
882 return err;
885 if (len > r->out.sd->size) {
886 r->out.sd->size = len;
887 return WERR_INSUFFICIENT_BUFFER;
890 r->out.sd->size = len;
891 r->out.sd->len = len;
892 r->out.sd->data = data;
894 return WERR_OK;
897 /*******************************************************************
898 _winreg_SetKeySecurity
899 ********************************************************************/
901 WERROR _winreg_SetKeySecurity(struct pipes_struct *p,
902 struct winreg_SetKeySecurity *r)
904 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
905 struct security_descriptor *secdesc = NULL;
906 WERROR err = WERR_OK;
908 if ( !key )
909 return WERR_BADFID;
911 /* access checks first */
913 if ( !(key->key->access_granted & SEC_STD_WRITE_DAC) )
914 return WERR_ACCESS_DENIED;
916 err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
917 r->in.sd->len, &secdesc));
918 if (!W_ERROR_IS_OK(err)) {
919 return err;
922 return reg_setkeysecurity(key, secdesc);
925 /*******************************************************************
926 _winreg_FlushKey
927 ********************************************************************/
929 WERROR _winreg_FlushKey(struct pipes_struct *p,
930 struct winreg_FlushKey *r)
932 /* I'm just replying OK because there's not a lot
933 here I see to do i --jerry */
935 return WERR_OK;
938 /*******************************************************************
939 _winreg_UnLoadKey
940 ********************************************************************/
942 WERROR _winreg_UnLoadKey(struct pipes_struct *p,
943 struct winreg_UnLoadKey *r)
945 /* fill in your code here if you think this call should
946 do anything */
948 p->rng_fault_state = True;
949 return WERR_NOT_SUPPORTED;
952 /*******************************************************************
953 _winreg_ReplaceKey
954 ********************************************************************/
956 WERROR _winreg_ReplaceKey(struct pipes_struct *p,
957 struct winreg_ReplaceKey *r)
959 /* fill in your code here if you think this call should
960 do anything */
962 p->rng_fault_state = True;
963 return WERR_NOT_SUPPORTED;
966 /*******************************************************************
967 _winreg_LoadKey
968 ********************************************************************/
970 WERROR _winreg_LoadKey(struct pipes_struct *p,
971 struct winreg_LoadKey *r)
973 /* fill in your code here if you think this call should
974 do anything */
976 p->rng_fault_state = True;
977 return WERR_NOT_SUPPORTED;
980 /*******************************************************************
981 _winreg_NotifyChangeKeyValue
982 ********************************************************************/
984 WERROR _winreg_NotifyChangeKeyValue(struct pipes_struct *p,
985 struct winreg_NotifyChangeKeyValue *r)
987 return WERR_NOT_SUPPORTED;
990 /*******************************************************************
991 _winreg_QueryMultipleValues
992 ********************************************************************/
994 WERROR _winreg_QueryMultipleValues(struct pipes_struct *p,
995 struct winreg_QueryMultipleValues *r)
997 struct winreg_QueryMultipleValues2 r2;
998 uint32_t needed = 0;
1000 r2.in.key_handle = r->in.key_handle;
1001 r2.in.values_in = r->in.values_in;
1002 r2.in.num_values = r->in.num_values;
1003 r2.in.offered = r->in.buffer_size;
1004 r2.in.buffer = r->in.buffer;
1005 r2.out.values_out = r->out.values_out;
1006 r2.out.needed = &needed;
1007 r2.out.buffer = r->out.buffer;
1009 return _winreg_QueryMultipleValues2(p, &r2);
1012 /*******************************************************************
1013 ********************************************************************/
1015 static WERROR construct_multiple_entry(TALLOC_CTX *mem_ctx,
1016 const char *valuename,
1017 uint32_t value_length,
1018 uint32_t offset,
1019 enum winreg_Type type,
1020 struct QueryMultipleValue *r)
1022 r->ve_valuename = talloc_zero(mem_ctx, struct winreg_ValNameBuf);
1023 if (r->ve_valuename == NULL) {
1024 return WERR_NOMEM;
1027 r->ve_valuename->name = talloc_strdup(r->ve_valuename, valuename ? valuename : "");
1028 if (r->ve_valuename->name == NULL) {
1029 return WERR_NOMEM;
1032 r->ve_valuename->size = strlen_m_term(r->ve_valuename->name)*2;
1033 r->ve_valuelen = value_length;
1034 r->ve_valueptr = offset;
1035 r->ve_type = type;
1037 return WERR_OK;
1040 /*******************************************************************
1041 _winreg_QueryMultipleValues2
1042 ********************************************************************/
1044 WERROR _winreg_QueryMultipleValues2(struct pipes_struct *p,
1045 struct winreg_QueryMultipleValues2 *r)
1047 struct registry_key *regkey = find_regkey_by_hnd(p, r->in.key_handle);
1048 struct registry_value *vals = NULL;
1049 const char **names = NULL;
1050 uint32_t offset = 0, num_vals = 0;
1051 DATA_BLOB result = data_blob_null;
1052 int i = 0;
1053 WERROR err = WERR_OK;
1055 if (!regkey) {
1056 return WERR_BADFID;
1059 names = talloc_zero_array(p->mem_ctx, const char *, r->in.num_values);
1060 if (names == NULL) {
1061 return WERR_NOMEM;
1064 for (i=0; i < r->in.num_values; i++) {
1065 if (r->in.values_in[i].ve_valuename &&
1066 r->in.values_in[i].ve_valuename->name) {
1067 names[i] = talloc_strdup(names,
1068 r->in.values_in[i].ve_valuename->name);
1069 if (names[i] == NULL) {
1070 return WERR_NOMEM;
1075 err = reg_querymultiplevalues(p->mem_ctx, regkey,
1076 r->in.num_values, names,
1077 &num_vals, &vals);
1078 if (!W_ERROR_IS_OK(err)) {
1079 return err;
1082 result = data_blob_talloc(p->mem_ctx, NULL, 0);
1084 for (i=0; i < r->in.num_values; i++) {
1085 const char *valuename = NULL;
1087 if (vals[i].data.length > 0) {
1088 if (!data_blob_append(p->mem_ctx, &result,
1089 vals[i].data.data,
1090 vals[i].data.length)) {
1091 return WERR_NOMEM;
1095 if (r->in.values_in[i].ve_valuename &&
1096 r->in.values_in[i].ve_valuename->name) {
1097 valuename = r->in.values_in[i].ve_valuename->name;
1100 err = construct_multiple_entry(r->out.values_out,
1101 valuename,
1102 vals[i].data.length,
1103 offset,
1104 vals[i].type,
1105 &r->out.values_out[i]);
1106 if (!W_ERROR_IS_OK(err)) {
1107 return err;
1110 offset += vals[i].data.length;
1113 *r->out.needed = result.length;
1115 if (r->in.num_values != num_vals) {
1116 return WERR_BADFILE;
1119 if (*r->in.offered >= *r->out.needed) {
1120 if (r->out.buffer) {
1121 memcpy(r->out.buffer, result.data, MIN(result.length, *r->in.offered));
1123 return WERR_OK;
1124 } else {
1125 return WERR_MORE_DATA;
1129 /*******************************************************************
1130 _winreg_DeleteKeyEx
1131 ********************************************************************/
1133 WERROR _winreg_DeleteKeyEx(struct pipes_struct *p,
1134 struct winreg_DeleteKeyEx *r)
1136 /* fill in your code here if you think this call should
1137 do anything */
1139 p->rng_fault_state = True;
1140 return WERR_NOT_SUPPORTED;