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 ) )