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
) ) {
86 return WERR_FILE_NOT_FOUND
;
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
))
123 return WERR_INVALID_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
);
230 return WERR_INVALID_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_FILE_NOT_FOUND
;
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
;
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
;
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
))
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
;
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
;
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_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
;
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
);
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
)) {
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
);
399 return WERR_INVALID_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
);
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
)) {
429 r
->out
.name
->name
= name
;
430 r
->out
.keyclass
->name
= "";
434 /*****************************************************************************
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
;
447 return WERR_INVALID_HANDLE
;
450 return WERR_INVALID_PARAMETER
;
452 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
455 err
= reg_enumvalue(p
->mem_ctx
, key
, r
->in
.enum_index
, &valname
, &val
);
456 if (!W_ERROR_IS_OK(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
;
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
;
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
;
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);
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 **********/
595 ret
= smbrun(shutdown_script
, NULL
, NULL
);
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());
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 **********/
629 ret
= smbrun(abort_shutdown_script
, NULL
, NULL
);
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
)
648 int num_services
= lp_numservices();
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
))) {
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
)) {
666 share_path
= lp_path(talloc_tos(), snum
);
668 /* make sure we have a path (e.g. [homes] ) */
669 if (strlen(share_path
) == 0) {
673 if (strncmp(share_path
, p
, strlen(share_path
)) == 0) {
679 return (snum
< num_services
) ? snum
: -1;
682 /*******************************************************************
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
);
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
);
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 /*******************************************************************
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
);
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
);
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 /*******************************************************************
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
766 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
767 return WERR_NOT_SUPPORTED
;
770 /*******************************************************************
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
;
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
)) {
793 if (!create_policy_hnd(p
, r
->out
.new_handle
, new_key
)) {
794 TALLOC_FREE(new_key
);
795 return WERR_FILE_NOT_FOUND
;
801 /*******************************************************************
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
;
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
);
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 /*******************************************************************
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
);
838 return WERR_INVALID_HANDLE
;
840 return reg_deletekey(parent
, r
->in
.key
.name
);
844 /*******************************************************************
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
);
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
;
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
)) {
885 err
= ntstatus_to_werror(marshall_sec_desc(p
->mem_ctx
, secdesc
,
887 if (!W_ERROR_IS_OK(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
;
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
;
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
)) {
928 return reg_setkeysecurity(key
, secdesc
);
931 /*******************************************************************
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 */
944 /*******************************************************************
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
954 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
955 return WERR_NOT_SUPPORTED
;
958 /*******************************************************************
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
968 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
969 return WERR_NOT_SUPPORTED
;
972 /*******************************************************************
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
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
,
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
;
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
;
1059 WERROR err
= WERR_OK
;
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
,
1084 if (!W_ERROR_IS_OK(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
,
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
,
1108 vals
[i
].data
.length
,
1111 &r
->out
.values_out
[i
]);
1112 if (!W_ERROR_IS_OK(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
));
1131 return WERR_MORE_DATA
;
1135 /*******************************************************************
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
1145 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1146 return WERR_NOT_SUPPORTED
;