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. */
25 #include "../librpc/gen_ndr/srv_winreg.h"
27 #include "registry/reg_api.h"
28 #include "registry/reg_api_regf.h"
29 #include "registry/reg_perfcount.h"
32 #include "lib/privileges.h"
33 #include "libcli/security/secdesc.h"
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 *)®key
)) {
48 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
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
;
73 result
= reg_openhive(p
->mem_ctx
, subkeyname
, access_desired
,
74 p
->session_info
->security_token
, &key
);
77 result
= reg_openkey(p
->mem_ctx
, parent
, subkeyname
,
78 access_desired
, &key
);
81 if ( !W_ERROR_IS_OK(result
) ) {
85 if ( !create_policy_hnd( p
, hnd
, key
) ) {
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
);
103 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
108 close_policy_hnd(p
, hnd
);
113 /********************************************************************
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
))
125 ZERO_STRUCTP(r
->out
.handle
);
130 /*******************************************************************
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 /*******************************************************************
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 /*******************************************************************
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 /*******************************************************************
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 /*******************************************************************
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 /*******************************************************************
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 /*******************************************************************
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 /*******************************************************************
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 /*******************************************************************
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 /*******************************************************************
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
);
232 return open_registry_key(p
, r
->out
.handle
, parent
, r
->in
.keyname
.name
, r
->in
.access_mask
);
235 /*******************************************************************
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
);
246 uint8_t *outbuf
= NULL
;
247 uint32_t outbuf_size
= 0;
249 bool free_buf
= False
;
250 bool free_prs
= False
;
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
))
272 status
= reg_perfcount_get_hkpd(
273 &prs_hkpd
, *r
->in
.data_size
, &outbuf_size
, NULL
);
274 outbuf
= (uint8_t *)prs_hkpd
.data_p
;
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
);
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
);
289 else if (isdigit(r
->in
.value_name
->name
[0])) {
290 /* we probably have a request for a specific object
292 if (!prs_init(&prs_hkpd
, *r
->in
.data_size
, p
->mem_ctx
, MARSHALL
))
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
;
301 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
302 r
->in
.value_name
->name
));
306 *r
->out
.type
= REG_BINARY
;
309 struct registry_value
*val
;
311 status
= reg_queryvalue(p
->mem_ctx
, regkey
, r
->in
.value_name
->name
,
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;
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
;
338 *r
->out
.data_length
= outbuf_size
;
339 *r
->out
.data_size
= outbuf_size
;
341 memcpy(r
->out
.data
, outbuf
, outbuf_size
);
346 if (free_prs
) prs_mem_free(&prs_hkpd
);
347 if (free_buf
) SAFE_FREE(outbuf
);
352 /*****************************************************************************
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
);
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
)) {
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;
389 /*****************************************************************************
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
);
401 return reg_getversion(r
->out
.version
);
405 /*****************************************************************************
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
);
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
)) {
428 r
->out
.keyclass
->name
= "";
432 /*****************************************************************************
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
;
448 return WERR_INVALID_PARAM
;
450 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
453 err
= reg_enumvalue(p
->mem_ctx
, key
, r
->in
.enum_index
, &valname
, &val
);
454 if (!W_ERROR_IS_OK(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
;
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
;
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
;
529 bool can_shutdown
= false;
531 shutdown_script
= lp_shutdown_script(p
->mem_ctx
);
532 if (!shutdown_script
) {
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
) {
545 chkmsg
= talloc_array(p
->mem_ctx
, char, strlen(msg
)+1);
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
) {
562 shutdown_script
= talloc_all_string_sub(p
->mem_ctx
,
563 shutdown_script
, "%t", str_timeout
);
564 if (!shutdown_script
) {
567 shutdown_script
= talloc_all_string_sub(p
->mem_ctx
,
568 shutdown_script
, "%r", do_reboot
);
569 if (!shutdown_script
) {
572 shutdown_script
= talloc_all_string_sub(p
->mem_ctx
,
573 shutdown_script
, "%f", f
);
574 if (!shutdown_script
) {
577 shutdown_script
= talloc_all_string_sub(p
->mem_ctx
,
578 shutdown_script
, "%x", str_reason
);
579 if (!shutdown_script
) {
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 **********/
593 ret
= smbrun( shutdown_script
, NULL
);
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(talloc_tos());
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 **********/
627 ret
= smbrun( abort_shutdown_script
, NULL
);
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
)
646 int num_services
= lp_numservices();
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
))) {
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
)) {
664 share_path
= lp_pathname(talloc_tos(), snum
);
666 /* make sure we have a path (e.g. [homes] ) */
667 if (strlen(share_path
) == 0) {
671 if (strncmp(share_path
, p
, strlen(share_path
)) == 0) {
677 return (snum
< num_services
) ? snum
: -1;
680 /*******************************************************************
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
);
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
);
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(talloc_tos(), snum
) ));
717 return reg_restorekey(regkey
, fname
);
720 /*******************************************************************
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
);
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
);
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(talloc_tos(), snum
) ));
751 return reg_savekey(regkey
, fname
);
754 /*******************************************************************
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
764 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
765 return WERR_NOT_SUPPORTED
;
768 /*******************************************************************
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
;
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
)) {
791 if (!create_policy_hnd(p
, r
->out
.new_handle
, new_key
)) {
792 TALLOC_FREE(new_key
);
799 /*******************************************************************
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
;
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
);
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 /*******************************************************************
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
);
838 return reg_deletekey(parent
, r
->in
.key
.name
);
842 /*******************************************************************
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
);
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
;
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
)) {
883 err
= ntstatus_to_werror(marshall_sec_desc(p
->mem_ctx
, secdesc
,
885 if (!W_ERROR_IS_OK(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
;
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
;
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
)) {
926 return reg_setkeysecurity(key
, secdesc
);
929 /*******************************************************************
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 */
942 /*******************************************************************
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
952 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
953 return WERR_NOT_SUPPORTED
;
956 /*******************************************************************
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
966 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
967 return WERR_NOT_SUPPORTED
;
970 /*******************************************************************
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
980 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
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
,
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
) {
1031 r
->ve_valuename
->name
= talloc_strdup(r
->ve_valuename
, valuename
? valuename
: "");
1032 if (r
->ve_valuename
->name
== NULL
) {
1036 r
->ve_valuename
->size
= strlen_m_term(r
->ve_valuename
->name
)*2;
1037 r
->ve_valuelen
= value_length
;
1038 r
->ve_valueptr
= offset
;
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
;
1057 WERROR err
= WERR_OK
;
1063 names
= talloc_zero_array(p
->mem_ctx
, const char *, r
->in
.num_values
);
1064 if (names
== NULL
) {
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
) {
1079 err
= reg_querymultiplevalues(p
->mem_ctx
, regkey
,
1080 r
->in
.num_values
, names
,
1082 if (!W_ERROR_IS_OK(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
,
1094 vals
[i
].data
.length
)) {
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
,
1106 vals
[i
].data
.length
,
1109 &r
->out
.values_out
[i
]);
1110 if (!W_ERROR_IS_OK(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
));
1129 return WERR_MORE_DATA
;
1133 /*******************************************************************
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
1143 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1144 return WERR_NOT_SUPPORTED
;