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 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;
341 enum winreg_CreateAction *paction = &action;
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 key_string.name = op->in.key_name;
383 class_string.name = op->in.class_name;
385 rpccli_winreg_CreateKey( pipe_hnd, mem_ctx, op->in.parent_key,
386 key_string, class_string, 0,
387 op->in.access, NULL, key_out,
390 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
394 op->out.key = key_out;
400 NTSTATUS cac_delete_subkeys_recursive( struct rpc_pipe_client * pipe_hnd,
401 TALLOC_CTX * mem_ctx, POLICY_HND * key )
407 uint32 num_subkeys, max_subkeylen, max_classlen;
408 uint32 num_values, max_valnamelen, maxvalbufsize;
410 struct winreg_String class_string;
415 /* First get the max subkey name length */
417 class_string.name = NULL;
418 status = rpccli_winreg_QueryInfoKey( pipe_hnd, mem_ctx, key,
419 &class_string, &num_subkeys,
420 &max_subkeylen, &max_classlen,
421 &num_values, &max_valnamelen,
422 &maxvalbufsize, &secdescsize,
426 if ( !NT_STATUS_IS_OK( status ) ) {
430 if ( (name_buffer = TALLOC_ARRAY( mem_ctx, char, max_subkeylen )) == NULL ) {
431 d_fprintf(stderr, "Memory allocation error.\n");
432 return NT_STATUS_NO_MEMORY;
436 while ( NT_STATUS_IS_OK( status ) ) {
437 struct winreg_String key_string;
438 struct winreg_StringBuf subkey_string;
441 memset( name_buffer, 0x0, max_subkeylen );
442 subkey_string.name = name_buffer;
443 subkey_string.length = 0;
444 subkey_string.size = max_subkeylen;
446 status = rpccli_winreg_EnumKey(pipe_hnd, mem_ctx, key, cur_key,
447 &subkey_string, NULL, NULL);
449 if ( !NT_STATUS_IS_OK( status ) )
452 /* copy the keyname and add the terminating NULL */
454 StrnCpy( subkeyname, subkey_string.name,
455 MIN(subkey_string.length, sizeof(subkeyname)-1) );
456 subkeyname[MIN(subkey_string.length, sizeof(subkeyname)-1)] = '\0';
458 /*try to open the key with full access */
460 key_string.name = subkeyname;
461 status = rpccli_winreg_OpenKey( pipe_hnd, mem_ctx, key,
462 key_string, 0, REG_KEY_ALL,
465 if ( !NT_STATUS_IS_OK( status ) )
468 status = cac_delete_subkeys_recursive( pipe_hnd, mem_ctx,
471 if ( !W_ERROR_EQUAL( ntstatus_to_werror(status), WERR_NO_MORE_ITEMS )
472 && !NT_STATUS_IS_OK( status ) )
475 /*flush the key just to be safe */
476 rpccli_winreg_FlushKey( pipe_hnd, mem_ctx, key );
478 /*close the key that we opened */
479 rpccli_winreg_CloseKey( pipe_hnd, mem_ctx, &subkey );
481 /*now we delete the subkey */
482 key_string.name = subkey_name;
483 status = rpccli_winreg_DeleteKey( pipe_hnd, mem_ctx, key,
495 int cac_RegDeleteKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
496 struct RegDeleteKey *op )
498 struct rpc_pipe_client *pipe_hnd = NULL;
499 struct winreg_String key_string;
504 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
505 hnd->status = NT_STATUS_INVALID_HANDLE;
509 if ( !op || !op->in.parent_key || !op->in.name || !mem_ctx ) {
510 hnd->status = NT_STATUS_INVALID_PARAMETER;
514 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
516 hnd->status = NT_STATUS_INVALID_HANDLE;
520 if ( op->in.recursive ) {
522 /* first open the key, and then delete all of
523 it's subkeys recursively */
525 struct RegOpenKey rok;
529 rok.in.parent_key = op->in.parent_key;
530 rok.in.name = op->in.name;
531 rok.in.access = REG_KEY_ALL;
533 if ( !cac_RegOpenKey( hnd, mem_ctx, &rok ) )
536 hnd->status = cac_delete_subkeys_recursive( pipe_hnd, mem_ctx,
539 /*close the key that we opened */
540 cac_RegClose( hnd, mem_ctx, rok.out.key );
542 if ( NT_STATUS_V( hnd->status ) !=
543 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED )
544 && !NT_STATUS_IS_OK( hnd->status ) )
547 /*now go on to actually delete the key */
550 key_string.name = op->in.name;
552 rpccli_winreg_DeleteKey( pipe_hnd, mem_ctx, op->in.parent_key,
555 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
562 int cac_RegDeleteValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
563 struct RegDeleteValue *op )
565 struct rpc_pipe_client *pipe_hnd = NULL;
566 struct winreg_String value_string;
571 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
572 hnd->status = NT_STATUS_INVALID_HANDLE;
576 if ( !op || !op->in.parent_key || !op->in.name || !mem_ctx ) {
577 hnd->status = NT_STATUS_INVALID_PARAMETER;
581 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
583 hnd->status = NT_STATUS_INVALID_HANDLE;
587 value_string.name = op->in.name;
589 rpccli_winreg_DeleteValue( pipe_hnd, mem_ctx,
590 op->in.parent_key, value_string );
592 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
599 int cac_RegQueryKeyInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
600 struct RegQueryKeyInfo *op )
602 struct rpc_pipe_client *pipe_hnd = NULL;
603 uint32 num_subkeys_out = 0;
604 uint32 long_subkey_out = 0;
605 uint32 long_class_out = 0;
606 uint32 num_values_out = 0;
607 uint32 long_value_out = 0;
608 uint32 long_data_out = 0;
609 uint32 secdesc_size = 0;
611 struct winreg_String class_string;
616 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
617 hnd->status = NT_STATUS_INVALID_HANDLE;
621 if ( !op || !op->in.key || !mem_ctx ) {
622 hnd->status = NT_STATUS_INVALID_PARAMETER;
626 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
628 hnd->status = NT_STATUS_INVALID_HANDLE;
632 hnd->status = rpccli_winreg_QueryInfoKey( pipe_hnd, mem_ctx,
641 &secdesc_size, &mod_time );
643 if ( !NT_STATUS_IS_OK( hnd->status ) )
646 if ( !class_string.name ) {
647 op->out.class_name = talloc_strdup( mem_ctx, "" );
649 op->out.class_name = talloc_strdup( mem_ctx, class_string.name );
652 if ( !op->out.class_name ) {
653 hnd->status = NT_STATUS_NO_MEMORY;
657 op->out.num_subkeys = num_subkeys_out;
658 op->out.longest_subkey = long_subkey_out;
659 op->out.longest_class = long_class_out;
660 op->out.num_values = num_values_out;
661 op->out.longest_value_name = long_value_out;
662 op->out.longest_value_data = long_data_out;
663 op->out.security_desc_size = secdesc_size;
664 op->out.last_write_time = nt_time_to_unix( mod_time );
669 int cac_RegQueryValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
670 struct RegQueryValue *op )
672 struct rpc_pipe_client *pipe_hnd = NULL;
673 struct winreg_String value_string;
674 REGVAL_BUFFER buffer;
675 REG_VALUE_DATA *data_out = NULL;
676 enum winreg_Type val_type;
677 enum winreg_Type *pval_type = &val_type;
679 uint32 buf_size = 4096;
680 uint32 *pbuf_size = &buf_size;
682 uint32 *plength = &length;
687 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
688 hnd->status = NT_STATUS_INVALID_HANDLE;
692 if ( !op || !op->in.key || !op->in.val_name || !mem_ctx ) {
693 hnd->status = NT_STATUS_INVALID_PARAMETER;
697 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
699 hnd->status = NT_STATUS_INVALID_HANDLE;
703 value_string.name = op->in.val_name;
705 if ( ( buf = TALLOC_ARRAY( mem_ctx, uint8, buf_size ) ) == NULL ) {
706 hnd->status = NT_STATUS_NO_MEMORY;
710 hnd->status = rpccli_winreg_QueryValue( pipe_hnd, mem_ctx, op->in.key,
711 value_string, &pval_type, &buf,
712 &pbuf_size, &plength );
714 if ( !NT_STATUS_IS_OK( hnd->status ) )
717 init_regval_buffer( &buffer, buf, length );
719 data_out = cac_MakeRegValueData( mem_ctx, val_type, buffer );
721 if ( errno == ENOMEM )
722 hnd->status = NT_STATUS_NO_MEMORY;
724 hnd->status = NT_STATUS_INVALID_PARAMETER;
729 op->out.type = val_type;
730 op->out.data = data_out;
736 int cac_RegEnumValues( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
737 struct RegEnumValues *op )
739 struct rpc_pipe_client *pipe_hnd = NULL;
741 REGVAL_BUFFER val_buf;
742 uint32 *types_out = NULL;
743 REG_VALUE_DATA **values_out = NULL;
744 char **val_names_out = NULL;
745 uint32 num_values_out = 0;
746 uint32 resume_idx = 0;
747 uint32 num_subkeys, max_subkeylen, max_classlen;
748 uint32 num_values, max_valnamelen, maxvalbufsize;
749 struct winreg_String class_string;
757 /* This is to avoid useless rpc calls, if the last
758 call exhausted all the keys, then we don't need
759 to go through everything again */
761 if ( NT_STATUS_V( hnd->status ) ==
762 NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED ) )
765 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
766 hnd->status = NT_STATUS_INVALID_HANDLE;
770 if ( !op || !op->in.key || op->in.max_values == 0 || !mem_ctx ) {
771 hnd->status = NT_STATUS_INVALID_PARAMETER;
775 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
777 hnd->status = NT_STATUS_INVALID_HANDLE;
781 /*we need to assume that the max number of values will be enumerated */
782 types_out = talloc_array( mem_ctx, uint32, op->in.max_values );
785 hnd->status = NT_STATUS_NO_MEMORY;
789 values_out = talloc_array( mem_ctx, REG_VALUE_DATA *,
793 TALLOC_FREE( types_out );
794 hnd->status = NT_STATUS_NO_MEMORY;
798 val_names_out = talloc_array( mem_ctx, char *, op->in.max_values );
800 if ( !val_names_out ) {
801 TALLOC_FREE( types_out );
802 TALLOC_FREE( values_out );
803 hnd->status = NT_STATUS_NO_MEMORY;
807 resume_idx = op->out.resume_idx;
809 class_string.name = NULL;
810 hnd->status = rpccli_winreg_QueryInfoKey( pipe_hnd, mem_ctx, op->in.key,
811 &class_string, &num_subkeys,
812 &max_subkeylen, &max_classlen,
813 &num_values, &max_valnamelen,
814 &maxvalbufsize, &secdescsize,
817 if ( !NT_STATUS_IS_OK(hnd->status) ) {
818 TALLOC_FREE( types_out );
819 TALLOC_FREE( values_out );
824 if ( (buffer = TALLOC_ARRAY( mem_ctx, uint8, maxvalbufsize )) == NULL ) {
825 TALLOC_FREE( types_out );
826 TALLOC_FREE( values_out );
827 hnd->status = NT_STATUS_NO_MEMORY;
832 if ( (name_buffer = TALLOC_ARRAY(mem_ctx, char, max_valnamelen)) == NULL ) {
833 TALLOC_FREE( types_out );
834 TALLOC_FREE( values_out );
835 TALLOC_FREE( buffer );
836 hnd->status = NT_STATUS_NO_MEMORY;
842 uint32 data_size = maxvalbufsize;
843 uint32 *pdata_size = &data_size;
844 uint32 data_length = 0;
845 uint32 *pdata_length = &data_length;
846 struct winreg_ValNameBuf name_buf;
847 enum winreg_Type *ptype = &types_out[num_values_out];
849 memset( name_buffer, 0x0, max_valnamelen );
850 name_buf.name = name_buffer;
851 name_buf.size = max_valnamelen;
854 hnd->status = rpccli_winreg_EnumValue( pipe_hnd, mem_ctx,
856 resume_idx, &name_buf,
861 if ( !NT_STATUS_IS_OK( hnd->status ) )
864 ZERO_STRUCT( val_buf );
865 init_regval_buffer( &val_buf, buffer, data_length );
867 values_out[num_values_out] = cac_MakeRegValueData( mem_ctx,
868 types_out[num_values_out],
870 val_names_out[num_values_out] = TALLOC_ARRAY( mem_ctx, char, name_buf.length+1 );
872 if ( !val_names_out[num_values_out]
873 || !values_out[num_values_out] ) {
874 hnd->status = NT_STATUS_NO_MEMORY;
878 StrnCpy( val_names_out[num_values_out], name_buf.name, name_buf.length );
879 (val_names_out[num_values_out])[name_buf.length] = '\0';
883 } while ( num_values_out < op->in.max_values );
885 if ( CAC_OP_FAILED( hnd->status ) )
888 op->out.types = types_out;
889 op->out.num_values = num_values_out;
890 op->out.value_names = val_names_out;
891 op->out.values = values_out;
892 op->out.resume_idx = resume_idx;
897 int cac_RegSetValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
898 struct RegSetValue *op )
900 struct rpc_pipe_client *pipe_hnd = NULL;
901 struct winreg_String value_string;
903 RPC_DATA_BLOB *buffer;
908 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
909 hnd->status = NT_STATUS_INVALID_HANDLE;
913 if ( !op || !op->in.key || !op->in.val_name || !mem_ctx ) {
914 hnd->status = NT_STATUS_INVALID_PARAMETER;
918 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
920 hnd->status = NT_STATUS_INVALID_HANDLE;
924 buffer = cac_MakeRpcDataBlob( mem_ctx, op->in.type, op->in.value );
927 if ( errno == ENOMEM )
928 hnd->status = NT_STATUS_NO_MEMORY;
930 hnd->status = NT_STATUS_INVALID_PARAMETER;
935 value_string.name = op->in.val_name;
937 rpccli_winreg_SetValue( pipe_hnd, mem_ctx, op->in.key,
938 value_string, op->in.type,
939 buffer->buffer, buffer->buf_len );
941 if ( !NT_STATUS_IS_OK( hnd->status ) )
945 hnd->status = rpccli_winreg_FlushKey( pipe_hnd, mem_ctx, op->in.key );
947 if ( !NT_STATUS_IS_OK( hnd->status ) )
955 int cac_RegGetVersion( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
956 struct RegGetVersion *op )
958 struct rpc_pipe_client *pipe_hnd = NULL;
964 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
965 hnd->status = NT_STATUS_INVALID_HANDLE;
969 if ( !op || !op->in.key || !mem_ctx ) {
970 hnd->status = NT_STATUS_INVALID_PARAMETER;
974 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
976 hnd->status = NT_STATUS_INVALID_HANDLE;
981 rpccli_winreg_GetVersion( pipe_hnd, mem_ctx, op->in.key,
984 if ( !NT_STATUS_IS_OK( hnd->status ) )
987 op->out.version = version_out;
992 int cac_RegGetKeySecurity( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
993 struct RegGetKeySecurity *op )
995 struct rpc_pipe_client *pipe_hnd = NULL;
996 struct KeySecurityData keysec;
998 ZERO_STRUCT( keysec );
1003 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
1004 hnd->status = NT_STATUS_INVALID_HANDLE;
1008 if ( !op || !op->in.key || op->in.info_type == 0 || !mem_ctx ) {
1009 hnd->status = NT_STATUS_INVALID_PARAMETER;
1013 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
1015 hnd->status = NT_STATUS_INVALID_HANDLE;
1020 rpccli_winreg_GetKeySecurity( pipe_hnd, mem_ctx, op->in.key,
1021 op->in.info_type, &keysec );
1023 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1027 #if 0 /* FIX ME!!!! unmarshall the security descriptor */
1028 op->out.size = buf.sd_size;
1029 op->out.descriptor = dup_sec_desc( mem_ctx, buf.sd );
1032 if ( op->out.descriptor == NULL ) {
1039 int cac_RegSetKeySecurity( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1040 struct RegSetKeySecurity *op )
1042 struct rpc_pipe_client *pipe_hnd = NULL;
1043 struct KeySecurityData keysec;
1045 ZERO_STRUCT( keysec );
1050 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
1051 hnd->status = NT_STATUS_INVALID_HANDLE;
1055 if ( !op || !op->in.key || op->in.info_type == 0 || op->in.size == 0
1056 || !op->in.descriptor || !mem_ctx ) {
1057 hnd->status = NT_STATUS_INVALID_PARAMETER;
1061 pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
1063 hnd->status = NT_STATUS_INVALID_HANDLE;
1067 /* FIXME!!! Marshall in the input sec_desc to struct KeySecurityData */
1069 rpccli_winreg_SetKeySecurity( pipe_hnd, mem_ctx, op->in.key,
1070 op->in.info_type, &keysec );
1072 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1079 int cac_Shutdown( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1080 struct Shutdown *op )
1082 SMBCSRV *srv = NULL;
1083 struct rpc_pipe_client *pipe_hnd = NULL;
1084 struct initshutdown_String msg_string;
1085 struct initshutdown_String_sub s;
1092 if ( !hnd->_internal.ctx ) {
1093 hnd->status = NT_STATUS_INVALID_HANDLE;
1097 if ( !op || !mem_ctx ) {
1098 hnd->status = NT_STATUS_INVALID_PARAMETER;
1102 srv = cac_GetServer( hnd );
1104 hnd->status = NT_STATUS_INVALID_HANDLE;
1108 /*initialize for winreg pipe if we have to */
1109 if ( !hnd->_internal.pipes[PI_INITSHUTDOWN] ) {
1112 cli_rpc_pipe_open_noauth( srv->cli, PI_INITSHUTDOWN,
1113 &( hnd->status ) ) ) ) {
1117 hnd->_internal.pipes[PI_INITSHUTDOWN] = True;
1120 pipe_hnd = cac_GetPipe( hnd, PI_INITSHUTDOWN );
1122 hnd->status = NT_STATUS_INVALID_HANDLE;
1126 msg = ( op->in.message !=
1127 NULL ) ? op->in.message : talloc_strdup( mem_ctx, "" );
1128 msg_string.name = &s;
1129 msg_string.name->name = msg;
1131 hnd->status = NT_STATUS_OK;
1133 if ( hnd->_internal.srv_level > SRV_WIN_NT4 ) {
1135 rpccli_initshutdown_InitEx( pipe_hnd, mem_ctx, NULL,
1143 if ( hnd->_internal.srv_level < SRV_WIN_2K
1144 || !NT_STATUS_IS_OK( hnd->status ) ) {
1146 rpccli_initshutdown_Init( pipe_hnd, mem_ctx, NULL,
1147 &msg_string, op->in.timeout,
1151 hnd->_internal.srv_level = SRV_WIN_NT4;
1154 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1161 int cac_AbortShutdown( CacServerHandle * hnd, TALLOC_CTX * mem_ctx )
1163 struct rpc_pipe_client *pipe_hnd = NULL;
1168 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_INITSHUTDOWN] ) {
1169 hnd->status = NT_STATUS_INVALID_HANDLE;
1173 pipe_hnd = cac_GetPipe( hnd, PI_INITSHUTDOWN );
1175 hnd->status = NT_STATUS_INVALID_HANDLE;
1179 hnd->status = rpccli_initshutdown_Abort( pipe_hnd, mem_ctx, NULL );
1181 if ( !NT_STATUS_IS_OK( hnd->status ) )