3 * Unix SMB/CIFS implementation.
4 * MS-RPC client library implementation (WINREG pipe)
5 * Copyright (C) Chris Nicholls 2005.
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 2 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, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "libmsrpc_internal.h"
25 WERROR
cac_delete_subkeys_recursive( struct rpc_pipe_client
* pipe_hnd
,
26 TALLOC_CTX
* mem_ctx
, POLICY_HND
* key
);
28 int cac_RegConnect( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
29 struct RegConnect
*op
)
32 struct rpc_pipe_client
*pipe_hnd
= NULL
;
33 POLICY_HND
*key
= NULL
;
39 if ( !hnd
->_internal
.ctx
) {
40 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
44 if ( !op
|| !op
->in
.root
|| !mem_ctx
) {
45 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
49 srv
= cac_GetServer( hnd
);
51 hnd
->status
= NT_STATUS_INVALID_CONNECTION
;
55 /*initialize for winreg pipe if we have to */
56 if ( !hnd
->_internal
.pipes
[PI_WINREG
] ) {
59 cli_rpc_pipe_open_noauth( srv
->cli
, PI_WINREG
,
60 &( hnd
->status
) ) ) ) {
64 hnd
->_internal
.pipes
[PI_WINREG
] = True
;
67 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
69 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
73 key
= talloc( mem_ctx
, POLICY_HND
);
75 hnd
->status
= NT_STATUS_NO_MEMORY
;
79 err
= rpccli_reg_connect( pipe_hnd
, mem_ctx
, op
->in
.root
,
81 hnd
->status
= werror_to_ntstatus( err
);
83 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
92 int cac_RegClose( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
95 struct rpc_pipe_client
*pipe_hnd
= NULL
;
101 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
102 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
106 if ( !key
|| !mem_ctx
) {
107 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
111 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
113 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
117 err
= rpccli_reg_close( pipe_hnd
, mem_ctx
, key
);
118 hnd
->status
= werror_to_ntstatus( err
);
120 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
127 int cac_RegOpenKey( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
128 struct RegOpenKey
*op
)
130 struct rpc_pipe_client
*pipe_hnd
= NULL
;
134 POLICY_HND
*parent_key
;
136 char *key_name
= NULL
;
139 struct RegConnect rc
;
144 if ( !hnd
->_internal
.ctx
) {
145 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
149 if ( !op
|| !op
->in
.name
|| !mem_ctx
) {
150 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
155 key_out
= talloc( mem_ctx
, POLICY_HND
);
157 hnd
->status
= NT_STATUS_NO_MEMORY
;
161 if ( !op
->in
.parent_key
) {
162 /*then we need to connect to the registry */
163 if ( !cac_ParseRegPath( op
->in
.name
, ®_type
, &key_name
) ) {
164 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
168 /*use cac_RegConnect because it handles the session setup */
171 rc
.in
.access
= op
->in
.access
;
172 rc
.in
.root
= reg_type
;
174 if ( !cac_RegConnect( hnd
, mem_ctx
, &rc
) ) {
178 /**if they only specified the root key, return the key we just opened*/
179 if ( key_name
== NULL
) {
180 op
->out
.key
= rc
.out
.key
;
184 parent_key
= rc
.out
.key
;
186 parent_key
= op
->in
.parent_key
;
187 key_name
= op
->in
.name
;
190 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
192 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
196 err
= rpccli_reg_open_entry( pipe_hnd
, mem_ctx
, parent_key
, key_name
,
197 op
->in
.access
, key_out
);
198 hnd
->status
= werror_to_ntstatus( err
);
200 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
204 if ( !op
->in
.parent_key
) {
205 /*then close the one that we opened above */
206 err
= rpccli_reg_close( pipe_hnd
, mem_ctx
, parent_key
);
207 hnd
->status
= werror_to_ntstatus( err
);
209 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
214 op
->out
.key
= key_out
;
219 int cac_RegEnumKeys( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
220 struct RegEnumKeys
*op
)
222 struct rpc_pipe_client
*pipe_hnd
= NULL
;
225 /*buffers for rpccli_reg_enum_key call */
227 fstring class_name_in
;
230 char **key_names_out
= NULL
;
231 char **class_names_out
= NULL
;
232 time_t *mod_times_out
= NULL
;
233 uint32 num_keys_out
= 0;
234 uint32 resume_idx
= 0;
239 /*this is to avoid useless rpc calls, if the last call exhausted all the keys, then we don't need to go through everything again */
240 if ( NT_STATUS_V( hnd
->status
) ==
241 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED
) )
244 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
245 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
249 if ( !op
|| op
->in
.max_keys
== 0 || !mem_ctx
) {
250 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
254 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
256 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
260 /**the only way to know how many keys to expect is to assume max_keys keys will be found*/
261 if (op
->in
.max_keys
) {
262 key_names_out
= TALLOC_ARRAY( mem_ctx
, char *, op
->in
.max_keys
);
263 if ( !key_names_out
) {
264 hnd
->status
= NT_STATUS_NO_MEMORY
;
268 class_names_out
= TALLOC_ARRAY( mem_ctx
, char *, op
->in
.max_keys
);
269 if ( !class_names_out
) {
270 hnd
->status
= NT_STATUS_NO_MEMORY
;
271 TALLOC_FREE( key_names_out
);
275 mod_times_out
= TALLOC_ARRAY( mem_ctx
, time_t, op
->in
.max_keys
);
276 if ( !mod_times_out
) {
277 hnd
->status
= NT_STATUS_NO_MEMORY
;
278 TALLOC_FREE( key_names_out
);
279 TALLOC_FREE( class_names_out
);
284 key_names_out
= NULL
;
285 class_names_out
= NULL
;
286 mod_times_out
= NULL
;
289 resume_idx
= op
->out
.resume_idx
;
292 err
= rpccli_reg_enum_key( pipe_hnd
, mem_ctx
, op
->in
.key
,
293 resume_idx
, key_name_in
,
295 &mod_times_out
[num_keys_out
] );
296 hnd
->status
= werror_to_ntstatus( err
);
298 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
299 /*don't increment any values */
303 key_names_out
[num_keys_out
] =
304 talloc_strdup( mem_ctx
, key_name_in
);
306 class_names_out
[num_keys_out
] =
307 talloc_strdup( mem_ctx
, class_name_in
);
309 if ( !key_names_out
[num_keys_out
]
310 || !class_names_out
[num_keys_out
] ) {
311 hnd
->status
= NT_STATUS_NO_MEMORY
;
317 } while ( num_keys_out
< op
->in
.max_keys
);
319 if ( CAC_OP_FAILED( hnd
->status
) ) {
320 op
->out
.num_keys
= 0;
324 op
->out
.resume_idx
= resume_idx
;
325 op
->out
.num_keys
= num_keys_out
;
326 op
->out
.key_names
= key_names_out
;
327 op
->out
.class_names
= class_names_out
;
328 op
->out
.mod_times
= mod_times_out
;
333 int cac_RegCreateKey( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
334 struct RegCreateKey
*op
)
336 struct rpc_pipe_client
*pipe_hnd
= NULL
;
341 struct RegOpenKey rok
;
346 if ( !hnd
->_internal
.ctx
) {
347 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
351 if ( !op
|| !op
->in
.parent_key
|| !op
->in
.key_name
|| !mem_ctx
) {
352 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
356 /*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized */
359 rok
.in
.name
= op
->in
.key_name
;
360 rok
.in
.access
= op
->in
.access
;
361 rok
.in
.parent_key
= op
->in
.parent_key
;
363 if ( cac_RegOpenKey( hnd
, mem_ctx
, &rok
) ) {
364 /*then we got the key, return */
365 op
->out
.key
= rok
.out
.key
;
369 /*just be ultra-safe */
370 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
372 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
376 key_out
= talloc( mem_ctx
, POLICY_HND
);
378 hnd
->status
= NT_STATUS_NO_MEMORY
;
382 err
= rpccli_reg_create_key_ex( pipe_hnd
, mem_ctx
, op
->in
.parent_key
,
383 op
->in
.key_name
, op
->in
.class_name
,
384 op
->in
.access
, key_out
);
385 hnd
->status
= werror_to_ntstatus( err
);
387 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
391 op
->out
.key
= key_out
;
397 WERROR
cac_delete_subkeys_recursive( struct rpc_pipe_client
* pipe_hnd
,
398 TALLOC_CTX
* mem_ctx
, POLICY_HND
* key
)
400 /*NOTE: using cac functions might result in a big(ger) memory bloat, and would probably be far less efficient
401 * so we use the cli_reg functions directly*/
403 WERROR err
= WERR_OK
;
412 while ( W_ERROR_IS_OK( err
) ) {
413 err
= rpccli_reg_enum_key( pipe_hnd
, mem_ctx
, key
, cur_key
,
414 subkey_name
, class_buf
,
417 if ( !W_ERROR_IS_OK( err
) )
420 /*try to open the key with full access */
421 err
= rpccli_reg_open_entry( pipe_hnd
, mem_ctx
, key
,
422 subkey_name
, REG_KEY_ALL
,
425 if ( !W_ERROR_IS_OK( err
) )
428 err
= cac_delete_subkeys_recursive( pipe_hnd
, mem_ctx
,
431 if ( !W_ERROR_EQUAL( err
, WERR_NO_MORE_ITEMS
)
432 && !W_ERROR_IS_OK( err
) )
435 /*flush the key just to be safe */
436 rpccli_reg_flush_key( pipe_hnd
, mem_ctx
, key
);
438 /*close the key that we opened */
439 rpccli_reg_close( pipe_hnd
, mem_ctx
, &subkey
);
441 /*now we delete the subkey */
442 err
= rpccli_reg_delete_key( pipe_hnd
, mem_ctx
, key
,
455 int cac_RegDeleteKey( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
456 struct RegDeleteKey
*op
)
458 struct rpc_pipe_client
*pipe_hnd
= NULL
;
464 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
465 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
469 if ( !op
|| !op
->in
.parent_key
|| !op
->in
.name
|| !mem_ctx
) {
470 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
474 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
476 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
480 if ( op
->in
.recursive
) {
481 /*first open the key, and then delete all of it's subkeys recursively */
482 struct RegOpenKey rok
;
486 rok
.in
.parent_key
= op
->in
.parent_key
;
487 rok
.in
.name
= op
->in
.name
;
488 rok
.in
.access
= REG_KEY_ALL
;
490 if ( !cac_RegOpenKey( hnd
, mem_ctx
, &rok
) )
493 err
= cac_delete_subkeys_recursive( pipe_hnd
, mem_ctx
,
496 /*close the key that we opened */
497 cac_RegClose( hnd
, mem_ctx
, rok
.out
.key
);
499 hnd
->status
= werror_to_ntstatus( err
);
501 if ( NT_STATUS_V( hnd
->status
) !=
502 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED
)
503 && !NT_STATUS_IS_OK( hnd
->status
) )
506 /*now go on to actually delete the key */
509 err
= rpccli_reg_delete_key( pipe_hnd
, mem_ctx
, op
->in
.parent_key
,
511 hnd
->status
= werror_to_ntstatus( err
);
513 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
520 int cac_RegDeleteValue( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
521 struct RegDeleteValue
*op
)
523 struct rpc_pipe_client
*pipe_hnd
= NULL
;
529 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
530 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
534 if ( !op
|| !op
->in
.parent_key
|| !op
->in
.name
|| !mem_ctx
) {
535 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
539 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
541 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
545 err
= rpccli_reg_delete_val( pipe_hnd
, mem_ctx
, op
->in
.parent_key
,
547 hnd
->status
= werror_to_ntstatus( err
);
549 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
558 /* JRA - disabled until fix. */
560 /* This code is currently broken so disable it - it needs to handle the ERROR_MORE_DATA
561 cleanly and resubmit the query. */
563 int cac_RegQueryKeyInfo( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
564 struct RegQueryKeyInfo
*op
)
566 struct rpc_pipe_client
*pipe_hnd
= NULL
;
569 char *class_name_out
= NULL
;
570 uint32 class_len
= 0;
571 uint32 num_subkeys_out
= 0;
572 uint32 long_subkey_out
= 0;
573 uint32 long_class_out
= 0;
574 uint32 num_values_out
= 0;
575 uint32 long_value_out
= 0;
576 uint32 long_data_out
= 0;
577 uint32 secdesc_size
= 0;
583 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
584 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
588 if ( !op
|| !op
->in
.key
|| !mem_ctx
) {
589 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
593 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
595 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
599 err
= rpccli_reg_query_key( pipe_hnd
, mem_ctx
, op
->in
.key
,
608 &secdesc_size
, &mod_time
);
610 hnd
->status
= werror_to_ntstatus( err
);
612 if ( !NT_STATUS_IS_OK( hnd
->status
) )
615 if ( !class_name_out
) {
616 op
->out
.class_name
= talloc_strdup( mem_ctx
, "" );
617 } else if ( class_len
!= 0 && class_name_out
[class_len
- 1] != '\0' ) {
618 /*then we need to add a '\0' */
620 TALLOC_SIZE( mem_ctx
,
621 sizeof( char ) * ( class_len
+ 1 ) );
623 memcpy( op
->out
.class_name
, class_name_out
, class_len
);
625 op
->out
.class_name
[class_len
] = '\0';
626 } else { /*then everything worked out fine in the function */
627 op
->out
.class_name
= talloc_strdup( mem_ctx
, class_name_out
);
630 if ( !op
->out
.class_name
) {
631 hnd
->status
= NT_STATUS_NO_MEMORY
;
635 op
->out
.num_subkeys
= num_subkeys_out
;
636 op
->out
.longest_subkey
= long_subkey_out
;
637 op
->out
.longest_class
= long_class_out
;
638 op
->out
.num_values
= num_values_out
;
639 op
->out
.longest_value_name
= long_value_out
;
640 op
->out
.longest_value_data
= long_data_out
;
641 op
->out
.security_desc_size
= secdesc_size
;
642 op
->out
.last_write_time
= nt_time_to_unix( &mod_time
);
648 int cac_RegQueryValue( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
649 struct RegQueryValue
*op
)
651 struct rpc_pipe_client
*pipe_hnd
= NULL
;
655 REGVAL_BUFFER buffer
;
656 REG_VALUE_DATA
*data_out
= NULL
;
661 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
662 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
666 if ( !op
|| !op
->in
.key
|| !op
->in
.val_name
|| !mem_ctx
) {
667 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
671 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
673 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
677 err
= rpccli_reg_query_value( pipe_hnd
, mem_ctx
, op
->in
.key
,
678 op
->in
.val_name
, &val_type
, &buffer
);
679 hnd
->status
= werror_to_ntstatus( err
);
681 if ( !NT_STATUS_IS_OK( hnd
->status
) )
684 data_out
= cac_MakeRegValueData( mem_ctx
, val_type
, buffer
);
686 if ( errno
== ENOMEM
)
687 hnd
->status
= NT_STATUS_NO_MEMORY
;
689 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
694 op
->out
.type
= val_type
;
695 op
->out
.data
= data_out
;
701 int cac_RegEnumValues( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
702 struct RegEnumValues
*op
)
704 struct rpc_pipe_client
*pipe_hnd
= NULL
;
707 /*buffers for rpccli_reg_enum_key call */
708 fstring val_name_buf
;
709 REGVAL_BUFFER val_buf
;
712 uint32
*types_out
= NULL
;
713 REG_VALUE_DATA
**values_out
= NULL
;
714 char **val_names_out
= NULL
;
715 uint32 num_values_out
= 0;
716 uint32 resume_idx
= 0;
721 /*this is to avoid useless rpc calls, if the last call exhausted all the keys, then we don't need to go through everything again */
722 if ( NT_STATUS_V( hnd
->status
) ==
723 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED
) )
726 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
727 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
731 if ( !op
|| !op
->in
.key
|| op
->in
.max_values
== 0 || !mem_ctx
) {
732 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
736 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
738 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
742 /*we need to assume that the max number of values will be enumerated */
743 if (op
->in
.max_values
) {
745 ( uint32
* ) TALLOC_ARRAY( mem_ctx
, int, op
->in
.max_values
);
747 hnd
->status
= NT_STATUS_NO_MEMORY
;
752 TALLOC_ARRAY( mem_ctx
, REG_VALUE_DATA
*, op
->in
.max_values
);
754 TALLOC_FREE( types_out
);
755 hnd
->status
= NT_STATUS_NO_MEMORY
;
759 val_names_out
= TALLOC_ARRAY( mem_ctx
, char *, op
->in
.max_values
);
760 if ( !val_names_out
) {
761 TALLOC_FREE( types_out
);
762 TALLOC_FREE( values_out
);
763 hnd
->status
= NT_STATUS_NO_MEMORY
;
769 val_names_out
= NULL
;
772 resume_idx
= op
->out
.resume_idx
;
774 ZERO_STRUCT( val_buf
);
776 err
= rpccli_reg_enum_val( pipe_hnd
, mem_ctx
, op
->in
.key
,
777 resume_idx
, val_name_buf
,
778 &types_out
[num_values_out
],
780 hnd
->status
= werror_to_ntstatus( err
);
782 if ( !NT_STATUS_IS_OK( hnd
->status
) )
785 values_out
[num_values_out
] =
786 cac_MakeRegValueData( mem_ctx
,
787 types_out
[num_values_out
],
789 val_names_out
[num_values_out
] =
790 talloc_strdup( mem_ctx
, val_name_buf
);
792 if ( !val_names_out
[num_values_out
]
793 || !values_out
[num_values_out
] ) {
794 hnd
->status
= NT_STATUS_NO_MEMORY
;
800 } while ( num_values_out
< op
->in
.max_values
);
802 if ( CAC_OP_FAILED( hnd
->status
) )
805 op
->out
.types
= types_out
;
806 op
->out
.num_values
= num_values_out
;
807 op
->out
.value_names
= val_names_out
;
808 op
->out
.values
= values_out
;
809 op
->out
.resume_idx
= resume_idx
;
814 int cac_RegSetValue( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
815 struct RegSetValue
*op
)
817 struct rpc_pipe_client
*pipe_hnd
= NULL
;
820 RPC_DATA_BLOB
*buffer
;
825 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
826 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
830 if ( !op
|| !op
->in
.key
|| !op
->in
.val_name
|| !mem_ctx
) {
831 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
835 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
837 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
841 buffer
= cac_MakeRpcDataBlob( mem_ctx
, op
->in
.type
, op
->in
.value
);
844 if ( errno
== ENOMEM
)
845 hnd
->status
= NT_STATUS_NO_MEMORY
;
847 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
852 err
= rpccli_reg_set_val( pipe_hnd
, mem_ctx
, op
->in
.key
,
853 op
->in
.val_name
, op
->in
.type
, buffer
);
854 hnd
->status
= werror_to_ntstatus( err
);
856 if ( !NT_STATUS_IS_OK( hnd
->status
) )
860 err
= rpccli_reg_flush_key( pipe_hnd
, mem_ctx
, op
->in
.key
);
861 hnd
->status
= werror_to_ntstatus( err
);
863 if ( !NT_STATUS_IS_OK( hnd
->status
) )
871 int cac_RegGetVersion( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
872 struct RegGetVersion
*op
)
874 struct rpc_pipe_client
*pipe_hnd
= NULL
;
882 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
883 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
887 if ( !op
|| !op
->in
.key
|| !mem_ctx
) {
888 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
892 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
894 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
898 err
= rpccli_reg_getversion( pipe_hnd
, mem_ctx
, op
->in
.key
,
900 hnd
->status
= werror_to_ntstatus( err
);
902 if ( !NT_STATUS_IS_OK( hnd
->status
) )
905 op
->out
.version
= version_out
;
910 int cac_RegGetKeySecurity( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
911 struct RegGetKeySecurity
*op
)
913 struct rpc_pipe_client
*pipe_hnd
= NULL
;
924 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
925 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
929 if ( !op
|| !op
->in
.key
|| op
->in
.info_type
== 0 || !mem_ctx
) {
930 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
934 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
936 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
940 err
= rpccli_reg_get_key_sec( pipe_hnd
, mem_ctx
, op
->in
.key
,
941 op
->in
.info_type
, &buf_size
, &buf
);
942 hnd
->status
= werror_to_ntstatus( err
);
945 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
949 op
->out
.size
= buf
.len
;
950 op
->out
.descriptor
= dup_sec_desc( mem_ctx
, buf
.sec
);
952 if ( op
->out
.descriptor
== NULL
) {
959 int cac_RegSetKeySecurity( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
960 struct RegSetKeySecurity
*op
)
962 struct rpc_pipe_client
*pipe_hnd
= NULL
;
968 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
969 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
973 if ( !op
|| !op
->in
.key
|| op
->in
.info_type
== 0 || op
->in
.size
== 0
974 || !op
->in
.descriptor
|| !mem_ctx
) {
975 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
979 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
981 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
985 err
= rpccli_reg_set_key_sec( pipe_hnd
, mem_ctx
, op
->in
.key
,
986 op
->in
.info_type
, op
->in
.size
,
988 hnd
->status
= werror_to_ntstatus( err
);
991 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
998 int cac_RegSaveKey( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
999 struct RegSaveKey
*op
)
1001 struct rpc_pipe_client
*pipe_hnd
= NULL
;
1007 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
1008 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1012 if ( !op
|| !op
->in
.key
|| !op
->in
.filename
|| !mem_ctx
) {
1013 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
1017 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
1019 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1023 err
= rpccli_reg_save_key( pipe_hnd
, mem_ctx
, op
->in
.key
,
1025 hnd
->status
= werror_to_ntstatus( err
);
1028 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
1035 int cac_Shutdown( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
1036 struct Shutdown
*op
)
1038 SMBCSRV
*srv
= NULL
;
1039 struct rpc_pipe_client
*pipe_hnd
= NULL
;
1046 if ( !hnd
->_internal
.ctx
) {
1047 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1051 if ( !op
|| !mem_ctx
) {
1052 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
1056 srv
= cac_GetServer( hnd
);
1058 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1062 /*initialize for winreg pipe if we have to */
1063 if ( !hnd
->_internal
.pipes
[PI_SHUTDOWN
] ) {
1066 cli_rpc_pipe_open_noauth( srv
->cli
, PI_SHUTDOWN
,
1067 &( hnd
->status
) ) ) ) {
1071 hnd
->_internal
.pipes
[PI_SHUTDOWN
] = True
;
1074 pipe_hnd
= cac_GetPipe( hnd
, PI_SHUTDOWN
);
1076 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1080 msg
= ( op
->in
.message
!=
1081 NULL
) ? op
->in
.message
: talloc_strdup( mem_ctx
, "" );
1083 hnd
->status
= NT_STATUS_OK
;
1085 if ( hnd
->_internal
.srv_level
> SRV_WIN_NT4
) {
1087 rpccli_shutdown_init_ex( pipe_hnd
, mem_ctx
, msg
,
1089 op
->in
.reboot
, op
->in
.force
,
1093 if ( hnd
->_internal
.srv_level
< SRV_WIN_2K
1094 || !NT_STATUS_IS_OK( hnd
->status
) ) {
1096 rpccli_shutdown_init( pipe_hnd
, mem_ctx
, msg
,
1097 op
->in
.timeout
, op
->in
.reboot
,
1100 hnd
->_internal
.srv_level
= SRV_WIN_NT4
;
1103 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
1110 int cac_AbortShutdown( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
)
1112 struct rpc_pipe_client
*pipe_hnd
= NULL
;
1117 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_SHUTDOWN
] ) {
1118 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1122 pipe_hnd
= cac_GetPipe( hnd
, PI_SHUTDOWN
);
1124 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1128 hnd
->status
= rpccli_shutdown_abort( pipe_hnd
, mem_ctx
);
1130 if ( !NT_STATUS_IS_OK( hnd
->status
) )