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 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/>.
22 #include "libmsrpc_internal.h"
24 NTSTATUS
cac_delete_subkeys_recursive(struct rpc_pipe_client
* pipe_hnd
,
25 TALLOC_CTX
* mem_ctx
, POLICY_HND
* key
);
27 int cac_RegConnect( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
28 struct RegConnect
*op
)
31 struct rpc_pipe_client
*pipe_hnd
= NULL
;
32 POLICY_HND
*key
= NULL
;
37 if ( !hnd
->_internal
.ctx
) {
38 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
42 if ( !op
|| !op
->in
.root
|| !mem_ctx
) {
43 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
47 srv
= cac_GetServer( hnd
);
49 hnd
->status
= NT_STATUS_INVALID_CONNECTION
;
53 /*initialize for winreg pipe if we have to */
54 if ( !hnd
->_internal
.pipes
[PI_WINREG
] ) {
57 cli_rpc_pipe_open_noauth( srv
->cli
, PI_WINREG
,
62 hnd
->_internal
.pipes
[PI_WINREG
] = True
;
65 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
67 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
71 key
= talloc( mem_ctx
, POLICY_HND
);
73 hnd
->status
= NT_STATUS_NO_MEMORY
;
78 rpccli_winreg_Connect( pipe_hnd
, mem_ctx
, op
->in
.root
,
81 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
90 int cac_RegClose( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
93 struct rpc_pipe_client
*pipe_hnd
= NULL
;
98 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
99 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
103 if ( !key
|| !mem_ctx
) {
104 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
108 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
110 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
114 hnd
->status
= rpccli_winreg_CloseKey( pipe_hnd
, mem_ctx
, key
);
116 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
123 int cac_RegOpenKey( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
124 struct RegOpenKey
*op
)
126 struct rpc_pipe_client
*pipe_hnd
= NULL
;
127 struct winreg_String key_string
;
130 POLICY_HND
*parent_key
;
132 char *key_name
= NULL
;
135 struct RegConnect rc
;
140 if ( !hnd
->_internal
.ctx
) {
141 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
145 if ( !op
|| !op
->in
.name
|| !mem_ctx
) {
146 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
151 key_out
= talloc( mem_ctx
, POLICY_HND
);
153 hnd
->status
= NT_STATUS_NO_MEMORY
;
157 if ( !op
->in
.parent_key
) {
158 /*then we need to connect to the registry */
159 if ( !cac_ParseRegPath( op
->in
.name
, ®_type
, &key_name
) ) {
160 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
164 /*use cac_RegConnect because it handles the session setup */
167 rc
.in
.access
= op
->in
.access
;
168 rc
.in
.root
= reg_type
;
170 if ( !cac_RegConnect( hnd
, mem_ctx
, &rc
) ) {
174 /**if they only specified the root key, return the key we just opened*/
175 if ( key_name
== NULL
) {
176 op
->out
.key
= rc
.out
.key
;
180 parent_key
= rc
.out
.key
;
182 parent_key
= op
->in
.parent_key
;
183 key_name
= op
->in
.name
;
186 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
188 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
192 key_string
.name
= key_name
;
194 rpccli_winreg_OpenKey( pipe_hnd
, mem_ctx
, parent_key
,
195 key_string
, 0, op
->in
.access
,
198 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
202 if ( !op
->in
.parent_key
) {
203 /*then close the one that we opened above */
205 rpccli_winreg_CloseKey( pipe_hnd
, mem_ctx
,
208 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
213 op
->out
.key
= key_out
;
218 int cac_RegEnumKeys( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
219 struct RegEnumKeys
*op
)
221 struct rpc_pipe_client
*pipe_hnd
= NULL
;
223 /*buffers for rpccli_reg_enum_key call */
225 fstring class_name_in
;
228 char **key_names_out
= NULL
;
229 char **class_names_out
= NULL
;
230 time_t *mod_times_out
= NULL
;
231 uint32 num_keys_out
= 0;
232 uint32 resume_idx
= 0;
237 /* This is to avoid useless rpc calls, if the last call
238 exhausted all the keys, then we don't need to go
239 through everything again */
241 if ( NT_STATUS_V( hnd
->status
) ==
242 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED
) )
245 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
246 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
250 if ( !op
|| op
->in
.max_keys
== 0 || !mem_ctx
) {
251 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
255 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
257 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
261 /* The only way to know how many keys to expect is to
262 assume max_keys keys will be found */
264 key_names_out
= TALLOC_ARRAY( mem_ctx
, char *, op
->in
.max_keys
);
265 if ( !key_names_out
) {
266 hnd
->status
= NT_STATUS_NO_MEMORY
;
270 class_names_out
= TALLOC_ARRAY( mem_ctx
, char *, op
->in
.max_keys
);
271 if ( !class_names_out
) {
272 hnd
->status
= NT_STATUS_NO_MEMORY
;
273 TALLOC_FREE( key_names_out
);
277 mod_times_out
= TALLOC_ARRAY( mem_ctx
, time_t, op
->in
.max_keys
);
278 if ( !mod_times_out
) {
279 hnd
->status
= NT_STATUS_NO_MEMORY
;
280 TALLOC_FREE( key_names_out
);
281 TALLOC_FREE( class_names_out
);
286 resume_idx
= op
->out
.resume_idx
;
291 rpccli_winreg_EnumKey( pipe_hnd
, mem_ctx
, op
->in
.key
,
292 resume_idx
, key_name_in
,
297 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
298 /*don't increment any values */
302 key_names_out
[num_keys_out
] =
303 talloc_strdup( mem_ctx
, key_name_in
);
305 class_names_out
[num_keys_out
] =
306 talloc_strdup( mem_ctx
, class_name_in
);
308 if ( !key_names_out
[num_keys_out
]
309 || !class_names_out
[num_keys_out
] ) {
310 hnd
->status
= NT_STATUS_NO_MEMORY
;
316 } while ( num_keys_out
< op
->in
.max_keys
);
318 if ( CAC_OP_FAILED( hnd
->status
) ) {
319 op
->out
.num_keys
= 0;
323 op
->out
.resume_idx
= resume_idx
;
324 op
->out
.num_keys
= num_keys_out
;
325 op
->out
.key_names
= key_names_out
;
326 op
->out
.class_names
= class_names_out
;
327 op
->out
.mod_times
= mod_times_out
;
332 int cac_RegCreateKey( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
333 struct RegCreateKey
*op
)
335 struct rpc_pipe_client
*pipe_hnd
= NULL
;
337 struct RegOpenKey rok
;
338 struct winreg_String key_string
, class_string
;
339 enum winreg_CreateAction action
= 0;
344 if ( !hnd
->_internal
.ctx
) {
345 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
349 if ( !op
|| !op
->in
.parent_key
|| !op
->in
.key_name
|| !mem_ctx
) {
350 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
354 /*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized */
357 rok
.in
.name
= op
->in
.key_name
;
358 rok
.in
.access
= op
->in
.access
;
359 rok
.in
.parent_key
= op
->in
.parent_key
;
361 if ( cac_RegOpenKey( hnd
, mem_ctx
, &rok
) ) {
362 /*then we got the key, return */
363 op
->out
.key
= rok
.out
.key
;
367 /*just be ultra-safe */
368 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
370 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
374 key_out
= talloc( mem_ctx
, POLICY_HND
);
376 hnd
->status
= NT_STATUS_NO_MEMORY
;
380 key_string
.name
= op
->in
.key_name
;
381 class_string
.name
= op
->in
.class_name
;
383 rpccli_winreg_CreateKey( pipe_hnd
, mem_ctx
, op
->in
.parent_key
,
384 key_string
, class_string
, 0,
385 op
->in
.access
, NULL
, key_out
,
388 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
392 op
->out
.key
= key_out
;
398 NTSTATUS
cac_delete_subkeys_recursive( struct rpc_pipe_client
* pipe_hnd
,
399 TALLOC_CTX
* mem_ctx
, POLICY_HND
* key
)
405 uint32 num_subkeys
, max_subkeylen
, max_classlen
;
406 uint32 num_values
, max_valnamelen
, maxvalbufsize
;
408 struct winreg_String class_string
;
413 /* First get the max subkey name length */
415 class_string
.name
= NULL
;
416 status
= rpccli_winreg_QueryInfoKey( pipe_hnd
, mem_ctx
, key
,
417 &class_string
, &num_subkeys
,
418 &max_subkeylen
, &max_classlen
,
419 &num_values
, &max_valnamelen
,
420 &maxvalbufsize
, &secdescsize
,
424 if ( !NT_STATUS_IS_OK( status
) ) {
428 if ( (name_buffer
= TALLOC_ARRAY( mem_ctx
, char, max_subkeylen
)) == NULL
) {
429 d_fprintf(stderr
, "Memory allocation error.\n");
430 return NT_STATUS_NO_MEMORY
;
434 while ( NT_STATUS_IS_OK( status
) ) {
435 struct winreg_String key_string
;
436 struct winreg_StringBuf subkey_string
;
439 memset( name_buffer
, 0x0, max_subkeylen
);
440 subkey_string
.name
= name_buffer
;
441 subkey_string
.length
= 0;
442 subkey_string
.size
= max_subkeylen
;
444 status
= rpccli_winreg_EnumKey(pipe_hnd
, mem_ctx
, key
, cur_key
,
445 &subkey_string
, NULL
, NULL
);
447 if ( !NT_STATUS_IS_OK( status
) )
450 /* copy the keyname and add the terminating NULL */
452 StrnCpy( subkeyname
, subkey_string
.name
,
453 MIN(subkey_string
.length
, sizeof(subkeyname
)-1) );
454 subkeyname
[MIN(subkey_string
.length
, sizeof(subkeyname
)-1)] = '\0';
456 /*try to open the key with full access */
458 key_string
.name
= subkeyname
;
459 status
= rpccli_winreg_OpenKey( pipe_hnd
, mem_ctx
, key
,
460 key_string
, 0, REG_KEY_ALL
,
463 if ( !NT_STATUS_IS_OK( status
) )
466 status
= cac_delete_subkeys_recursive( pipe_hnd
, mem_ctx
,
469 if ( !W_ERROR_EQUAL( ntstatus_to_werror(status
), WERR_NO_MORE_ITEMS
)
470 && !NT_STATUS_IS_OK( status
) )
473 /*flush the key just to be safe */
474 rpccli_winreg_FlushKey( pipe_hnd
, mem_ctx
, key
);
476 /*close the key that we opened */
477 rpccli_winreg_CloseKey( pipe_hnd
, mem_ctx
, &subkey
);
479 /*now we delete the subkey */
480 key_string
.name
= subkey_name
;
481 status
= rpccli_winreg_DeleteKey( pipe_hnd
, mem_ctx
, key
,
493 int cac_RegDeleteKey( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
494 struct RegDeleteKey
*op
)
496 struct rpc_pipe_client
*pipe_hnd
= NULL
;
497 struct winreg_String key_string
;
502 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
503 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
507 if ( !op
|| !op
->in
.parent_key
|| !op
->in
.name
|| !mem_ctx
) {
508 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
512 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
514 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
518 if ( op
->in
.recursive
) {
520 /* first open the key, and then delete all of
521 it's subkeys recursively */
523 struct RegOpenKey rok
;
527 rok
.in
.parent_key
= op
->in
.parent_key
;
528 rok
.in
.name
= op
->in
.name
;
529 rok
.in
.access
= REG_KEY_ALL
;
531 if ( !cac_RegOpenKey( hnd
, mem_ctx
, &rok
) )
534 hnd
->status
= cac_delete_subkeys_recursive( pipe_hnd
, mem_ctx
,
537 /*close the key that we opened */
538 cac_RegClose( hnd
, mem_ctx
, rok
.out
.key
);
540 if ( NT_STATUS_V( hnd
->status
) !=
541 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED
)
542 && !NT_STATUS_IS_OK( hnd
->status
) )
545 /*now go on to actually delete the key */
548 key_string
.name
= op
->in
.name
;
550 rpccli_winreg_DeleteKey( pipe_hnd
, mem_ctx
, op
->in
.parent_key
,
553 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
560 int cac_RegDeleteValue( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
561 struct RegDeleteValue
*op
)
563 struct rpc_pipe_client
*pipe_hnd
= NULL
;
564 struct winreg_String value_string
;
569 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
570 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
574 if ( !op
|| !op
->in
.parent_key
|| !op
->in
.name
|| !mem_ctx
) {
575 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
579 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
581 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
585 value_string
.name
= op
->in
.name
;
587 rpccli_winreg_DeleteValue( pipe_hnd
, mem_ctx
,
588 op
->in
.parent_key
, value_string
);
590 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
597 int cac_RegQueryKeyInfo( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
598 struct RegQueryKeyInfo
*op
)
600 struct rpc_pipe_client
*pipe_hnd
= NULL
;
601 uint32 num_subkeys_out
= 0;
602 uint32 long_subkey_out
= 0;
603 uint32 long_class_out
= 0;
604 uint32 num_values_out
= 0;
605 uint32 long_value_out
= 0;
606 uint32 long_data_out
= 0;
607 uint32 secdesc_size
= 0;
609 struct winreg_String class_string
;
614 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
615 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
619 if ( !op
|| !op
->in
.key
|| !mem_ctx
) {
620 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
624 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
626 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
630 hnd
->status
= rpccli_winreg_QueryInfoKey( pipe_hnd
, mem_ctx
,
639 &secdesc_size
, &mod_time
);
641 if ( !NT_STATUS_IS_OK( hnd
->status
) )
644 if ( !class_string
.name
) {
645 op
->out
.class_name
= talloc_strdup( mem_ctx
, "" );
647 op
->out
.class_name
= talloc_strdup( mem_ctx
, class_string
.name
);
650 if ( !op
->out
.class_name
) {
651 hnd
->status
= NT_STATUS_NO_MEMORY
;
655 op
->out
.num_subkeys
= num_subkeys_out
;
656 op
->out
.longest_subkey
= long_subkey_out
;
657 op
->out
.longest_class
= long_class_out
;
658 op
->out
.num_values
= num_values_out
;
659 op
->out
.longest_value_name
= long_value_out
;
660 op
->out
.longest_value_data
= long_data_out
;
661 op
->out
.security_desc_size
= secdesc_size
;
662 op
->out
.last_write_time
= nt_time_to_unix( mod_time
);
667 int cac_RegQueryValue( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
668 struct RegQueryValue
*op
)
670 struct rpc_pipe_client
*pipe_hnd
= NULL
;
671 struct winreg_String value_string
;
672 REGVAL_BUFFER buffer
;
673 REG_VALUE_DATA
*data_out
= NULL
;
674 enum winreg_Type val_type
;
676 uint32 buf_size
= 4096;
682 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
683 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
687 if ( !op
|| !op
->in
.key
|| !op
->in
.val_name
|| !mem_ctx
) {
688 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
692 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
694 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
698 value_string
.name
= op
->in
.val_name
;
700 if ( ( buf
= TALLOC_ARRAY( mem_ctx
, uint8
, buf_size
) ) == NULL
) {
701 hnd
->status
= NT_STATUS_NO_MEMORY
;
705 hnd
->status
= rpccli_winreg_QueryValue( pipe_hnd
, mem_ctx
, op
->in
.key
,
706 value_string
, &val_type
, buf
,
707 &buf_size
, &length
);
709 if ( !NT_STATUS_IS_OK( hnd
->status
) )
712 init_regval_buffer( &buffer
, buf
, length
);
714 data_out
= cac_MakeRegValueData( mem_ctx
, val_type
, buffer
);
716 if ( errno
== ENOMEM
)
717 hnd
->status
= NT_STATUS_NO_MEMORY
;
719 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
724 op
->out
.type
= val_type
;
725 op
->out
.data
= data_out
;
731 int cac_RegEnumValues( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
732 struct RegEnumValues
*op
)
734 struct rpc_pipe_client
*pipe_hnd
= NULL
;
736 REGVAL_BUFFER val_buf
;
737 uint32
*types_out
= NULL
;
738 REG_VALUE_DATA
**values_out
= NULL
;
739 char **val_names_out
= NULL
;
740 uint32 num_values_out
= 0;
741 uint32 resume_idx
= 0;
742 uint32 num_subkeys
, max_subkeylen
, max_classlen
;
743 uint32 num_values
, max_valnamelen
, maxvalbufsize
;
744 struct winreg_String class_string
;
752 /* This is to avoid useless rpc calls, if the last
753 call exhausted all the keys, then we don't need
754 to go through everything again */
756 if ( NT_STATUS_V( hnd
->status
) ==
757 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED
) )
760 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
761 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
765 if ( !op
|| !op
->in
.key
|| op
->in
.max_values
== 0 || !mem_ctx
) {
766 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
770 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
772 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
776 /*we need to assume that the max number of values will be enumerated */
777 types_out
= TALLOC_ARRAY( mem_ctx
, uint32
, op
->in
.max_values
);
780 hnd
->status
= NT_STATUS_NO_MEMORY
;
784 values_out
= TALLOC_ARRAY( mem_ctx
, REG_VALUE_DATA
*,
788 TALLOC_FREE( types_out
);
789 hnd
->status
= NT_STATUS_NO_MEMORY
;
793 val_names_out
= TALLOC_ARRAY( mem_ctx
, char *, op
->in
.max_values
);
795 if ( !val_names_out
) {
796 TALLOC_FREE( types_out
);
797 TALLOC_FREE( values_out
);
798 hnd
->status
= NT_STATUS_NO_MEMORY
;
802 resume_idx
= op
->out
.resume_idx
;
804 class_string
.name
= NULL
;
805 hnd
->status
= rpccli_winreg_QueryInfoKey( pipe_hnd
, mem_ctx
, op
->in
.key
,
806 &class_string
, &num_subkeys
,
807 &max_subkeylen
, &max_classlen
,
808 &num_values
, &max_valnamelen
,
809 &maxvalbufsize
, &secdescsize
,
812 if ( !NT_STATUS_IS_OK(hnd
->status
) ) {
813 TALLOC_FREE( types_out
);
814 TALLOC_FREE( values_out
);
819 if ( (buffer
= TALLOC_ARRAY( mem_ctx
, uint8
, maxvalbufsize
)) == NULL
) {
820 TALLOC_FREE( types_out
);
821 TALLOC_FREE( values_out
);
822 hnd
->status
= NT_STATUS_NO_MEMORY
;
827 if ( (name_buffer
= TALLOC_ARRAY(mem_ctx
, char, max_valnamelen
)) == NULL
) {
828 TALLOC_FREE( types_out
);
829 TALLOC_FREE( values_out
);
830 TALLOC_FREE( buffer
);
831 hnd
->status
= NT_STATUS_NO_MEMORY
;
837 uint32 data_size
= maxvalbufsize
;
838 uint32 data_length
= 0;
839 struct winreg_ValNameBuf name_buf
;
841 memset( name_buffer
, 0x0, max_valnamelen
);
842 name_buf
.name
= name_buffer
;
843 name_buf
.size
= max_valnamelen
;
846 hnd
->status
= rpccli_winreg_EnumValue( pipe_hnd
, mem_ctx
,
848 resume_idx
, &name_buf
,
849 &types_out
[num_values_out
], buffer
,
853 if ( !NT_STATUS_IS_OK( hnd
->status
) )
856 ZERO_STRUCT( val_buf
);
857 init_regval_buffer( &val_buf
, buffer
, data_length
);
859 values_out
[num_values_out
] = cac_MakeRegValueData( mem_ctx
,
860 types_out
[num_values_out
],
862 val_names_out
[num_values_out
] = TALLOC_ARRAY( mem_ctx
, char, name_buf
.length
+1 );
864 if ( !val_names_out
[num_values_out
]
865 || !values_out
[num_values_out
] ) {
866 hnd
->status
= NT_STATUS_NO_MEMORY
;
870 StrnCpy( val_names_out
[num_values_out
], name_buf
.name
, name_buf
.length
);
871 (val_names_out
[num_values_out
])[name_buf
.length
] = '\0';
875 } while ( num_values_out
< op
->in
.max_values
);
877 if ( CAC_OP_FAILED( hnd
->status
) )
880 op
->out
.types
= types_out
;
881 op
->out
.num_values
= num_values_out
;
882 op
->out
.value_names
= val_names_out
;
883 op
->out
.values
= values_out
;
884 op
->out
.resume_idx
= resume_idx
;
889 int cac_RegSetValue( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
890 struct RegSetValue
*op
)
892 struct rpc_pipe_client
*pipe_hnd
= NULL
;
893 struct winreg_String value_string
;
895 RPC_DATA_BLOB
*buffer
;
900 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
901 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
905 if ( !op
|| !op
->in
.key
|| !op
->in
.val_name
|| !mem_ctx
) {
906 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
910 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
912 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
916 buffer
= cac_MakeRpcDataBlob( mem_ctx
, op
->in
.type
, op
->in
.value
);
919 if ( errno
== ENOMEM
)
920 hnd
->status
= NT_STATUS_NO_MEMORY
;
922 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
927 value_string
.name
= op
->in
.val_name
;
929 rpccli_winreg_SetValue( pipe_hnd
, mem_ctx
, op
->in
.key
,
930 value_string
, op
->in
.type
,
931 buffer
->buffer
, buffer
->buf_len
);
933 if ( !NT_STATUS_IS_OK( hnd
->status
) )
937 hnd
->status
= rpccli_winreg_FlushKey( pipe_hnd
, mem_ctx
, op
->in
.key
);
939 if ( !NT_STATUS_IS_OK( hnd
->status
) )
947 int cac_RegGetVersion( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
948 struct RegGetVersion
*op
)
950 struct rpc_pipe_client
*pipe_hnd
= NULL
;
956 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
957 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
961 if ( !op
|| !op
->in
.key
|| !mem_ctx
) {
962 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
966 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
968 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
973 rpccli_winreg_GetVersion( pipe_hnd
, mem_ctx
, op
->in
.key
,
976 if ( !NT_STATUS_IS_OK( hnd
->status
) )
979 op
->out
.version
= version_out
;
984 int cac_RegGetKeySecurity( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
985 struct RegGetKeySecurity
*op
)
987 struct rpc_pipe_client
*pipe_hnd
= NULL
;
988 struct KeySecurityData keysec
;
990 ZERO_STRUCT( keysec
);
995 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
996 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1000 if ( !op
|| !op
->in
.key
|| op
->in
.info_type
== 0 || !mem_ctx
) {
1001 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
1005 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
1007 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1012 rpccli_winreg_GetKeySecurity( pipe_hnd
, mem_ctx
, op
->in
.key
,
1013 op
->in
.info_type
, &keysec
);
1015 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
1019 #if 0 /* FIX ME!!!! unmarshall the security descriptor */
1020 op
->out
.size
= buf
.sd_size
;
1021 op
->out
.descriptor
= dup_sec_desc( mem_ctx
, buf
.sd
);
1024 if ( op
->out
.descriptor
== NULL
) {
1031 int cac_RegSetKeySecurity( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
1032 struct RegSetKeySecurity
*op
)
1034 struct rpc_pipe_client
*pipe_hnd
= NULL
;
1035 struct KeySecurityData keysec
;
1037 ZERO_STRUCT( keysec
);
1042 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
] ) {
1043 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1047 if ( !op
|| !op
->in
.key
|| op
->in
.info_type
== 0 || op
->in
.size
== 0
1048 || !op
->in
.descriptor
|| !mem_ctx
) {
1049 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
1053 pipe_hnd
= cac_GetPipe( hnd
, PI_WINREG
);
1055 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1059 /* FIXME!!! Marshall in the input sec_desc to struct KeySecurityData */
1061 rpccli_winreg_SetKeySecurity( pipe_hnd
, mem_ctx
, op
->in
.key
,
1062 op
->in
.info_type
, &keysec
);
1064 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
1071 int cac_Shutdown( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
,
1072 struct Shutdown
*op
)
1074 SMBCSRV
*srv
= NULL
;
1075 struct rpc_pipe_client
*pipe_hnd
= NULL
;
1076 struct initshutdown_String msg_string
;
1077 struct initshutdown_String_sub s
;
1084 if ( !hnd
->_internal
.ctx
) {
1085 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1089 if ( !op
|| !mem_ctx
) {
1090 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
1094 srv
= cac_GetServer( hnd
);
1096 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1100 /*initialize for winreg pipe if we have to */
1101 if ( !hnd
->_internal
.pipes
[PI_INITSHUTDOWN
] ) {
1104 cli_rpc_pipe_open_noauth( srv
->cli
, PI_INITSHUTDOWN
,
1105 &( hnd
->status
) ) ) ) {
1109 hnd
->_internal
.pipes
[PI_INITSHUTDOWN
] = True
;
1112 pipe_hnd
= cac_GetPipe( hnd
, PI_INITSHUTDOWN
);
1114 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1118 msg
= ( op
->in
.message
!=
1119 NULL
) ? op
->in
.message
: talloc_strdup( mem_ctx
, "" );
1120 msg_string
.name
= &s
;
1121 msg_string
.name
->name
= msg
;
1123 hnd
->status
= NT_STATUS_OK
;
1125 if ( hnd
->_internal
.srv_level
> SRV_WIN_NT4
) {
1127 rpccli_initshutdown_InitEx( pipe_hnd
, mem_ctx
, NULL
,
1135 if ( hnd
->_internal
.srv_level
< SRV_WIN_2K
1136 || !NT_STATUS_IS_OK( hnd
->status
) ) {
1138 rpccli_initshutdown_Init( pipe_hnd
, mem_ctx
, NULL
,
1139 &msg_string
, op
->in
.timeout
,
1143 hnd
->_internal
.srv_level
= SRV_WIN_NT4
;
1146 if ( !NT_STATUS_IS_OK( hnd
->status
) ) {
1153 int cac_AbortShutdown( CacServerHandle
* hnd
, TALLOC_CTX
* mem_ctx
)
1155 struct rpc_pipe_client
*pipe_hnd
= NULL
;
1160 if ( !hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_INITSHUTDOWN
] ) {
1161 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1165 pipe_hnd
= cac_GetPipe( hnd
, PI_INITSHUTDOWN
);
1167 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1171 hnd
->status
= rpccli_initshutdown_Abort( pipe_hnd
, mem_ctx
, NULL
);
1173 if ( !NT_STATUS_IS_OK( hnd
->status
) )