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, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "libmsrpc_internal.h"
25 NTSTATUS 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;
38 if ( !hnd->_internal.ctx ) {
39 hnd->status = NT_STATUS_INVALID_HANDLE;
43 if ( !op || !op->in.root || !mem_ctx ) {
44 hnd->status = NT_STATUS_INVALID_PARAMETER;
48 srv = cac_GetServer( hnd );
50 hnd->status = NT_STATUS_INVALID_CONNECTION;
54 /*initialize for winreg pipe if we have to */
55 if ( !hnd->_internal.pipes[PI_WINREG] ) {
58 cli_rpc_pipe_open_noauth( srv->cli, PI_WINREG,
63 hnd->_internal.pipes[PI_WINREG] = True;
66 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
68 hnd->status = NT_STATUS_INVALID_HANDLE;
72 key = talloc( mem_ctx, POLICY_HND );
74 hnd->status = NT_STATUS_NO_MEMORY;
79 rpccli_winreg_Connect( pipe_hnd, mem_ctx, op->in.root,
82 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
91 int cac_RegClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
94 struct rpc_pipe_client *pipe_hnd = NULL;
99 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
100 hnd->status = NT_STATUS_INVALID_HANDLE;
104 if ( !key || !mem_ctx ) {
105 hnd->status = NT_STATUS_INVALID_PARAMETER;
109 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
111 hnd->status = NT_STATUS_INVALID_HANDLE;
115 hnd->status = rpccli_winreg_CloseKey( pipe_hnd, mem_ctx, key );
117 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
124 int cac_RegOpenKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
125 struct RegOpenKey *op )
127 struct rpc_pipe_client *pipe_hnd = NULL;
128 struct winreg_String key_string;
131 POLICY_HND *parent_key;
133 char *key_name = NULL;
136 struct RegConnect rc;
141 if ( !hnd->_internal.ctx ) {
142 hnd->status = NT_STATUS_INVALID_HANDLE;
146 if ( !op || !op->in.name || !mem_ctx ) {
147 hnd->status = NT_STATUS_INVALID_PARAMETER;
152 key_out = talloc( mem_ctx, POLICY_HND );
154 hnd->status = NT_STATUS_NO_MEMORY;
158 if ( !op->in.parent_key ) {
159 /*then we need to connect to the registry */
160 if ( !cac_ParseRegPath( op->in.name, ®_type, &key_name ) ) {
161 hnd->status = NT_STATUS_INVALID_PARAMETER;
165 /*use cac_RegConnect because it handles the session setup */
168 rc.in.access = op->in.access;
169 rc.in.root = reg_type;
171 if ( !cac_RegConnect( hnd, mem_ctx, &rc ) ) {
175 /**if they only specified the root key, return the key we just opened*/
176 if ( key_name == NULL ) {
177 op->out.key = rc.out.key;
181 parent_key = rc.out.key;
183 parent_key = op->in.parent_key;
184 key_name = op->in.name;
187 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
189 hnd->status = NT_STATUS_INVALID_HANDLE;
193 key_string.name = key_name;
195 rpccli_winreg_OpenKey( pipe_hnd, mem_ctx, parent_key,
196 key_string, 0, op->in.access,
199 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
203 if ( !op->in.parent_key ) {
204 /*then close the one that we opened above */
206 rpccli_winreg_CloseKey( pipe_hnd, mem_ctx,
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;
224 /*buffers for rpccli_reg_enum_key call */
226 fstring class_name_in;
229 char **key_names_out = NULL;
230 char **class_names_out = NULL;
231 time_t *mod_times_out = NULL;
232 uint32 num_keys_out = 0;
233 uint32 resume_idx = 0;
238 /* This is to avoid useless rpc calls, if the last call
239 exhausted all the keys, then we don't need to go
240 through everything again */
242 if ( NT_STATUS_V( hnd->status ) ==
243 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED ) )
246 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
247 hnd->status = NT_STATUS_INVALID_HANDLE;
251 if ( !op || op->in.max_keys == 0 || !mem_ctx ) {
252 hnd->status = NT_STATUS_INVALID_PARAMETER;
256 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
258 hnd->status = NT_STATUS_INVALID_HANDLE;
262 /* The only way to know how many keys to expect is to
263 assume max_keys keys will be found */
265 key_names_out = TALLOC_ARRAY( mem_ctx, char *, op->in.max_keys );
266 if ( !key_names_out ) {
267 hnd->status = NT_STATUS_NO_MEMORY;
271 class_names_out = TALLOC_ARRAY( mem_ctx, char *, op->in.max_keys );
272 if ( !class_names_out ) {
273 hnd->status = NT_STATUS_NO_MEMORY;
274 TALLOC_FREE( key_names_out );
278 mod_times_out = TALLOC_ARRAY( mem_ctx, time_t, op->in.max_keys );
279 if ( !mod_times_out ) {
280 hnd->status = NT_STATUS_NO_MEMORY;
281 TALLOC_FREE( key_names_out );
282 TALLOC_FREE( class_names_out );
287 resume_idx = op->out.resume_idx;
292 rpccli_winreg_EnumKey( pipe_hnd, mem_ctx, op->in.key,
293 resume_idx, key_name_in,
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;
338 struct RegOpenKey rok;
339 struct winreg_String key_string, class_string;
340 enum winreg_CreateAction action = 0;
345 if ( !hnd->_internal.ctx ) {
346 hnd->status = NT_STATUS_INVALID_HANDLE;
350 if ( !op || !op->in.parent_key || !op->in.key_name || !mem_ctx ) {
351 hnd->status = NT_STATUS_INVALID_PARAMETER;
355 /*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized */
358 rok.in.name = op->in.key_name;
359 rok.in.access = op->in.access;
360 rok.in.parent_key = op->in.parent_key;
362 if ( cac_RegOpenKey( hnd, mem_ctx, &rok ) ) {
363 /*then we got the key, return */
364 op->out.key = rok.out.key;
368 /*just be ultra-safe */
369 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
371 hnd->status = NT_STATUS_INVALID_HANDLE;
375 key_out = talloc( mem_ctx, POLICY_HND );
377 hnd->status = NT_STATUS_NO_MEMORY;
381 key_string.name = op->in.key_name;
382 class_string.name = op->in.class_name;
384 rpccli_winreg_CreateKey( pipe_hnd, mem_ctx, op->in.parent_key,
385 key_string, class_string, 0,
386 op->in.access, NULL, key_out,
389 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
393 op->out.key = key_out;
399 NTSTATUS cac_delete_subkeys_recursive( struct rpc_pipe_client * pipe_hnd,
400 TALLOC_CTX * mem_ctx, POLICY_HND * key )
406 uint32 num_subkeys, max_subkeylen, max_classlen;
407 uint32 num_values, max_valnamelen, maxvalbufsize;
409 struct winreg_String class_string;
414 /* First get the max subkey name length */
416 class_string.name = NULL;
417 status = rpccli_winreg_QueryInfoKey( pipe_hnd, mem_ctx, key,
418 &class_string, &num_subkeys,
419 &max_subkeylen, &max_classlen,
420 &num_values, &max_valnamelen,
421 &maxvalbufsize, &secdescsize,
425 if ( !NT_STATUS_IS_OK( status ) ) {
429 if ( (name_buffer = TALLOC_ARRAY( mem_ctx, char, max_subkeylen )) == NULL ) {
430 d_fprintf(stderr, "Memory allocation error.\n");
431 return NT_STATUS_NO_MEMORY;
435 while ( NT_STATUS_IS_OK( status ) ) {
436 struct winreg_String key_string;
437 struct winreg_StringBuf subkey_string;
440 memset( name_buffer, 0x0, max_subkeylen );
441 subkey_string.name = name_buffer;
442 subkey_string.length = 0;
443 subkey_string.size = max_subkeylen;
445 status = rpccli_winreg_EnumKey(pipe_hnd, mem_ctx, key, cur_key,
446 &subkey_string, NULL, NULL);
448 if ( !NT_STATUS_IS_OK( status ) )
451 /* copy the keyname and add the terminating NULL */
453 StrnCpy( subkeyname, subkey_string.name,
454 MIN(subkey_string.length, sizeof(subkeyname)-1) );
455 subkeyname[MIN(subkey_string.length, sizeof(subkeyname)-1)] = '\0';
457 /*try to open the key with full access */
459 key_string.name = subkeyname;
460 status = rpccli_winreg_OpenKey( pipe_hnd, mem_ctx, key,
461 key_string, 0, REG_KEY_ALL,
464 if ( !NT_STATUS_IS_OK( status ) )
467 status = cac_delete_subkeys_recursive( pipe_hnd, mem_ctx,
470 if ( !W_ERROR_EQUAL( ntstatus_to_werror(status), WERR_NO_MORE_ITEMS )
471 && !NT_STATUS_IS_OK( status ) )
474 /*flush the key just to be safe */
475 rpccli_winreg_FlushKey( pipe_hnd, mem_ctx, key );
477 /*close the key that we opened */
478 rpccli_winreg_CloseKey( pipe_hnd, mem_ctx, &subkey );
480 /*now we delete the subkey */
481 key_string.name = subkey_name;
482 status = rpccli_winreg_DeleteKey( pipe_hnd, mem_ctx, key,
494 int cac_RegDeleteKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
495 struct RegDeleteKey *op )
497 struct rpc_pipe_client *pipe_hnd = NULL;
498 struct winreg_String key_string;
503 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
504 hnd->status = NT_STATUS_INVALID_HANDLE;
508 if ( !op || !op->in.parent_key || !op->in.name || !mem_ctx ) {
509 hnd->status = NT_STATUS_INVALID_PARAMETER;
513 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
515 hnd->status = NT_STATUS_INVALID_HANDLE;
519 if ( op->in.recursive ) {
521 /* first open the key, and then delete all of
522 it's subkeys recursively */
524 struct RegOpenKey rok;
528 rok.in.parent_key = op->in.parent_key;
529 rok.in.name = op->in.name;
530 rok.in.access = REG_KEY_ALL;
532 if ( !cac_RegOpenKey( hnd, mem_ctx, &rok ) )
535 hnd->status = cac_delete_subkeys_recursive( pipe_hnd, mem_ctx,
538 /*close the key that we opened */
539 cac_RegClose( hnd, mem_ctx, rok.out.key );
541 if ( NT_STATUS_V( hnd->status ) !=
542 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED )
543 && !NT_STATUS_IS_OK( hnd->status ) )
546 /*now go on to actually delete the key */
549 key_string.name = op->in.name;
551 rpccli_winreg_DeleteKey( pipe_hnd, mem_ctx, op->in.parent_key,
554 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
561 int cac_RegDeleteValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
562 struct RegDeleteValue *op )
564 struct rpc_pipe_client *pipe_hnd = NULL;
565 struct winreg_String value_string;
570 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
571 hnd->status = NT_STATUS_INVALID_HANDLE;
575 if ( !op || !op->in.parent_key || !op->in.name || !mem_ctx ) {
576 hnd->status = NT_STATUS_INVALID_PARAMETER;
580 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
582 hnd->status = NT_STATUS_INVALID_HANDLE;
586 value_string.name = op->in.name;
588 rpccli_winreg_DeleteValue( pipe_hnd, mem_ctx,
589 op->in.parent_key, value_string );
591 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
598 int cac_RegQueryKeyInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
599 struct RegQueryKeyInfo *op )
601 struct rpc_pipe_client *pipe_hnd = NULL;
602 uint32 num_subkeys_out = 0;
603 uint32 long_subkey_out = 0;
604 uint32 long_class_out = 0;
605 uint32 num_values_out = 0;
606 uint32 long_value_out = 0;
607 uint32 long_data_out = 0;
608 uint32 secdesc_size = 0;
610 struct winreg_String class_string;
615 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
616 hnd->status = NT_STATUS_INVALID_HANDLE;
620 if ( !op || !op->in.key || !mem_ctx ) {
621 hnd->status = NT_STATUS_INVALID_PARAMETER;
625 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
627 hnd->status = NT_STATUS_INVALID_HANDLE;
631 hnd->status = rpccli_winreg_QueryInfoKey( pipe_hnd, mem_ctx,
640 &secdesc_size, &mod_time );
642 if ( !NT_STATUS_IS_OK( hnd->status ) )
645 if ( !class_string.name ) {
646 op->out.class_name = talloc_strdup( mem_ctx, "" );
648 op->out.class_name = talloc_strdup( mem_ctx, class_string.name );
651 if ( !op->out.class_name ) {
652 hnd->status = NT_STATUS_NO_MEMORY;
656 op->out.num_subkeys = num_subkeys_out;
657 op->out.longest_subkey = long_subkey_out;
658 op->out.longest_class = long_class_out;
659 op->out.num_values = num_values_out;
660 op->out.longest_value_name = long_value_out;
661 op->out.longest_value_data = long_data_out;
662 op->out.security_desc_size = secdesc_size;
663 op->out.last_write_time = nt_time_to_unix( mod_time );
668 int cac_RegQueryValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
669 struct RegQueryValue *op )
671 struct rpc_pipe_client *pipe_hnd = NULL;
672 struct winreg_String value_string;
673 REGVAL_BUFFER buffer;
674 REG_VALUE_DATA *data_out = NULL;
675 enum winreg_Type val_type;
677 uint32 buf_size = 4096;
683 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
684 hnd->status = NT_STATUS_INVALID_HANDLE;
688 if ( !op || !op->in.key || !op->in.val_name || !mem_ctx ) {
689 hnd->status = NT_STATUS_INVALID_PARAMETER;
693 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
695 hnd->status = NT_STATUS_INVALID_HANDLE;
699 value_string.name = op->in.val_name;
701 if ( ( buf = TALLOC_ARRAY( mem_ctx, uint8, buf_size ) ) == NULL ) {
702 hnd->status = NT_STATUS_NO_MEMORY;
706 hnd->status = rpccli_winreg_QueryValue( pipe_hnd, mem_ctx, op->in.key,
707 value_string, &val_type, buf,
708 &buf_size, &length );
710 if ( !NT_STATUS_IS_OK( hnd->status ) )
713 init_regval_buffer( &buffer, buf, length );
715 data_out = cac_MakeRegValueData( mem_ctx, val_type, buffer );
717 if ( errno == ENOMEM )
718 hnd->status = NT_STATUS_NO_MEMORY;
720 hnd->status = NT_STATUS_INVALID_PARAMETER;
725 op->out.type = val_type;
726 op->out.data = data_out;
732 int cac_RegEnumValues( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
733 struct RegEnumValues *op )
735 struct rpc_pipe_client *pipe_hnd = NULL;
737 REGVAL_BUFFER val_buf;
738 uint32 *types_out = NULL;
739 REG_VALUE_DATA **values_out = NULL;
740 char **val_names_out = NULL;
741 uint32 num_values_out = 0;
742 uint32 resume_idx = 0;
743 uint32 num_subkeys, max_subkeylen, max_classlen;
744 uint32 num_values, max_valnamelen, maxvalbufsize;
745 struct winreg_String class_string;
753 /* This is to avoid useless rpc calls, if the last
754 call exhausted all the keys, then we don't need
755 to go through everything again */
757 if ( NT_STATUS_V( hnd->status ) ==
758 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED ) )
761 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
762 hnd->status = NT_STATUS_INVALID_HANDLE;
766 if ( !op || !op->in.key || op->in.max_values == 0 || !mem_ctx ) {
767 hnd->status = NT_STATUS_INVALID_PARAMETER;
771 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
773 hnd->status = NT_STATUS_INVALID_HANDLE;
777 /*we need to assume that the max number of values will be enumerated */
778 types_out = TALLOC_ARRAY( mem_ctx, uint32, op->in.max_values );
781 hnd->status = NT_STATUS_NO_MEMORY;
785 values_out = TALLOC_ARRAY( mem_ctx, REG_VALUE_DATA *,
789 TALLOC_FREE( types_out );
790 hnd->status = NT_STATUS_NO_MEMORY;
794 val_names_out = TALLOC_ARRAY( mem_ctx, char *, op->in.max_values );
796 if ( !val_names_out ) {
797 TALLOC_FREE( types_out );
798 TALLOC_FREE( values_out );
799 hnd->status = NT_STATUS_NO_MEMORY;
803 resume_idx = op->out.resume_idx;
805 class_string.name = NULL;
806 hnd->status = rpccli_winreg_QueryInfoKey( pipe_hnd, mem_ctx, op->in.key,
807 &class_string, &num_subkeys,
808 &max_subkeylen, &max_classlen,
809 &num_values, &max_valnamelen,
810 &maxvalbufsize, &secdescsize,
813 if ( !NT_STATUS_IS_OK(hnd->status) ) {
814 TALLOC_FREE( types_out );
815 TALLOC_FREE( values_out );
820 if ( (buffer = TALLOC_ARRAY( mem_ctx, uint8, maxvalbufsize )) == NULL ) {
821 TALLOC_FREE( types_out );
822 TALLOC_FREE( values_out );
823 hnd->status = NT_STATUS_NO_MEMORY;
828 if ( (name_buffer = TALLOC_ARRAY(mem_ctx, char, max_valnamelen)) == NULL ) {
829 TALLOC_FREE( types_out );
830 TALLOC_FREE( values_out );
831 TALLOC_FREE( buffer );
832 hnd->status = NT_STATUS_NO_MEMORY;
838 uint32 data_size = maxvalbufsize;
839 uint32 data_length = 0;
840 struct winreg_ValNameBuf name_buf;
842 memset( name_buffer, 0x0, max_valnamelen );
843 name_buf.name = name_buffer;
844 name_buf.size = max_valnamelen;
847 hnd->status = rpccli_winreg_EnumValue( pipe_hnd, mem_ctx,
849 resume_idx, &name_buf,
850 &types_out[num_values_out], buffer,
854 if ( !NT_STATUS_IS_OK( hnd->status ) )
857 ZERO_STRUCT( val_buf );
858 init_regval_buffer( &val_buf, buffer, data_length );
860 values_out[num_values_out] = cac_MakeRegValueData( mem_ctx,
861 types_out[num_values_out],
863 val_names_out[num_values_out] = TALLOC_ARRAY( mem_ctx, char, name_buf.length+1 );
865 if ( !val_names_out[num_values_out]
866 || !values_out[num_values_out] ) {
867 hnd->status = NT_STATUS_NO_MEMORY;
871 StrnCpy( val_names_out[num_values_out], name_buf.name, name_buf.length );
872 (val_names_out[num_values_out])[name_buf.length] = '\0';
876 } while ( num_values_out < op->in.max_values );
878 if ( CAC_OP_FAILED( hnd->status ) )
881 op->out.types = types_out;
882 op->out.num_values = num_values_out;
883 op->out.value_names = val_names_out;
884 op->out.values = values_out;
885 op->out.resume_idx = resume_idx;
890 int cac_RegSetValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
891 struct RegSetValue *op )
893 struct rpc_pipe_client *pipe_hnd = NULL;
894 struct winreg_String value_string;
896 RPC_DATA_BLOB *buffer;
901 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
902 hnd->status = NT_STATUS_INVALID_HANDLE;
906 if ( !op || !op->in.key || !op->in.val_name || !mem_ctx ) {
907 hnd->status = NT_STATUS_INVALID_PARAMETER;
911 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
913 hnd->status = NT_STATUS_INVALID_HANDLE;
917 buffer = cac_MakeRpcDataBlob( mem_ctx, op->in.type, op->in.value );
920 if ( errno == ENOMEM )
921 hnd->status = NT_STATUS_NO_MEMORY;
923 hnd->status = NT_STATUS_INVALID_PARAMETER;
928 value_string.name = op->in.val_name;
930 rpccli_winreg_SetValue( pipe_hnd, mem_ctx, op->in.key,
931 value_string, op->in.type,
932 buffer->buffer, buffer->buf_len );
934 if ( !NT_STATUS_IS_OK( hnd->status ) )
938 hnd->status = rpccli_winreg_FlushKey( pipe_hnd, mem_ctx, op->in.key );
940 if ( !NT_STATUS_IS_OK( hnd->status ) )
948 int cac_RegGetVersion( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
949 struct RegGetVersion *op )
951 struct rpc_pipe_client *pipe_hnd = NULL;
957 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
958 hnd->status = NT_STATUS_INVALID_HANDLE;
962 if ( !op || !op->in.key || !mem_ctx ) {
963 hnd->status = NT_STATUS_INVALID_PARAMETER;
967 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
969 hnd->status = NT_STATUS_INVALID_HANDLE;
974 rpccli_winreg_GetVersion( pipe_hnd, mem_ctx, op->in.key,
977 if ( !NT_STATUS_IS_OK( hnd->status ) )
980 op->out.version = version_out;
985 int cac_RegGetKeySecurity( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
986 struct RegGetKeySecurity *op )
988 struct rpc_pipe_client *pipe_hnd = NULL;
989 struct KeySecurityData keysec;
991 ZERO_STRUCT( keysec );
996 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
997 hnd->status = NT_STATUS_INVALID_HANDLE;
1001 if ( !op || !op->in.key || op->in.info_type == 0 || !mem_ctx ) {
1002 hnd->status = NT_STATUS_INVALID_PARAMETER;
1006 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
1008 hnd->status = NT_STATUS_INVALID_HANDLE;
1013 rpccli_winreg_GetKeySecurity( pipe_hnd, mem_ctx, op->in.key,
1014 op->in.info_type, &keysec );
1016 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1020 #if 0 /* FIX ME!!!! unmarshall the security descriptor */
1021 op->out.size = buf.sd_size;
1022 op->out.descriptor = dup_sec_desc( mem_ctx, buf.sd );
1025 if ( op->out.descriptor == NULL ) {
1032 int cac_RegSetKeySecurity( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1033 struct RegSetKeySecurity *op )
1035 struct rpc_pipe_client *pipe_hnd = NULL;
1036 struct KeySecurityData keysec;
1038 ZERO_STRUCT( keysec );
1043 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
1044 hnd->status = NT_STATUS_INVALID_HANDLE;
1048 if ( !op || !op->in.key || op->in.info_type == 0 || op->in.size == 0
1049 || !op->in.descriptor || !mem_ctx ) {
1050 hnd->status = NT_STATUS_INVALID_PARAMETER;
1054 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
1056 hnd->status = NT_STATUS_INVALID_HANDLE;
1060 /* FIXME!!! Marshall in the input sec_desc to struct KeySecurityData */
1062 rpccli_winreg_SetKeySecurity( pipe_hnd, mem_ctx, op->in.key,
1063 op->in.info_type, &keysec );
1065 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1072 int cac_Shutdown( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1073 struct Shutdown *op )
1075 SMBCSRV *srv = NULL;
1076 struct rpc_pipe_client *pipe_hnd = NULL;
1077 struct initshutdown_String msg_string;
1078 struct initshutdown_String_sub s;
1085 if ( !hnd->_internal.ctx ) {
1086 hnd->status = NT_STATUS_INVALID_HANDLE;
1090 if ( !op || !mem_ctx ) {
1091 hnd->status = NT_STATUS_INVALID_PARAMETER;
1095 srv = cac_GetServer( hnd );
1097 hnd->status = NT_STATUS_INVALID_HANDLE;
1101 /*initialize for winreg pipe if we have to */
1102 if ( !hnd->_internal.pipes[PI_INITSHUTDOWN] ) {
1105 cli_rpc_pipe_open_noauth( srv->cli, PI_INITSHUTDOWN,
1106 &( hnd->status ) ) ) ) {
1110 hnd->_internal.pipes[PI_INITSHUTDOWN] = True;
1113 pipe_hnd = cac_GetPipe( hnd, PI_INITSHUTDOWN );
1115 hnd->status = NT_STATUS_INVALID_HANDLE;
1119 msg = ( op->in.message !=
1120 NULL ) ? op->in.message : talloc_strdup( mem_ctx, "" );
1121 msg_string.name = &s;
1122 msg_string.name->name = msg;
1124 hnd->status = NT_STATUS_OK;
1126 if ( hnd->_internal.srv_level > SRV_WIN_NT4 ) {
1128 rpccli_initshutdown_InitEx( pipe_hnd, mem_ctx, NULL,
1136 if ( hnd->_internal.srv_level < SRV_WIN_2K
1137 || !NT_STATUS_IS_OK( hnd->status ) ) {
1139 rpccli_initshutdown_Init( pipe_hnd, mem_ctx, NULL,
1140 &msg_string, op->in.timeout,
1144 hnd->_internal.srv_level = SRV_WIN_NT4;
1147 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1154 int cac_AbortShutdown( CacServerHandle * hnd, TALLOC_CTX * mem_ctx )
1156 struct rpc_pipe_client *pipe_hnd = NULL;
1161 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_INITSHUTDOWN] ) {
1162 hnd->status = NT_STATUS_INVALID_HANDLE;
1166 pipe_hnd = cac_GetPipe( hnd, PI_INITSHUTDOWN );
1168 hnd->status = NT_STATUS_INVALID_HANDLE;
1172 hnd->status = rpccli_initshutdown_Abort( pipe_hnd, mem_ctx, NULL );
1174 if ( !NT_STATUS_IS_OK( hnd->status ) )