2 * Unix SMB/CIFS implementation.
3 * MS-RPC client library implementation (WINREG pipe)
4 * Copyright (C) Chris Nicholls 2005.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libmsrpc_internal.h"
25 int cac_RegConnect(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegConnect
*op
) {
27 struct rpc_pipe_client
*pipe_hnd
= NULL
;
28 POLICY_HND
*key
= NULL
;
33 if(!hnd
->_internal
.ctx
) {
34 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
38 if(!op
|| !op
->in
.root
|| !mem_ctx
) {
39 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
43 srv
= cac_GetServer(hnd
);
45 hnd
->status
= NT_STATUS_INVALID_CONNECTION
;
49 /*initialize for winreg pipe if we have to*/
50 if(!hnd
->_internal
.pipes
[PI_WINREG
]) {
51 if(!(pipe_hnd
= cli_rpc_pipe_open_noauth(srv
->cli
, PI_WINREG
, &hnd
->status
))) {
55 hnd
->_internal
.pipes
[PI_WINREG
] = True
;
58 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
60 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
64 key
= talloc(mem_ctx
, POLICY_HND
);
66 hnd
->status
= NT_STATUS_NO_MEMORY
;
70 hnd
->status
= rpccli_winreg_connect( pipe_hnd
, mem_ctx
, op
->in
.root
, op
->in
.access
, key
);
72 if(!NT_STATUS_IS_OK(hnd
->status
)) {
81 int cac_RegClose(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, POLICY_HND
*key
) {
82 struct rpc_pipe_client
*pipe_hnd
= NULL
;
87 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
88 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
92 if(!key
|| !mem_ctx
) {
93 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
97 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
99 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
103 hnd
->status
= rpccli_winreg_CloseKey(pipe_hnd
, mem_ctx
, key
);
105 if(!NT_STATUS_IS_OK(hnd
->status
)) {
112 int cac_RegOpenKey(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegOpenKey
*op
) {
113 struct rpc_pipe_client
*pipe_hnd
= NULL
;
114 struct winreg_String key_string
;
117 POLICY_HND
*parent_key
;
119 char *key_name
= NULL
;
122 struct RegConnect rc
;
127 if(!hnd
->_internal
.ctx
) {
128 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
132 if(!op
|| !op
->in
.name
|| !mem_ctx
) {
133 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
138 key_out
= talloc(mem_ctx
, POLICY_HND
);
140 hnd
->status
= NT_STATUS_NO_MEMORY
;
144 if(!op
->in
.parent_key
) {
145 /*then we need to connect to the registry*/
146 if(!cac_ParseRegPath(op
->in
.name
, ®_type
, &key_name
)) {
147 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
151 /*use cac_RegConnect because it handles the session setup*/
154 rc
.in
.access
= op
->in
.access
;
155 rc
.in
.root
= reg_type
;
157 if(!cac_RegConnect(hnd
, mem_ctx
, &rc
)) {
161 /**if they only specified the root key, return the key we just opened*/
162 if(key_name
== NULL
) {
163 op
->out
.key
= rc
.out
.key
;
167 parent_key
= rc
.out
.key
;
170 parent_key
= op
->in
.parent_key
;
171 key_name
= op
->in
.name
;
174 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
176 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
180 key_string
.name
= key_name
;
181 hnd
->status
= rpccli_winreg_OpenKey( pipe_hnd
, mem_ctx
, parent_key
, key_string
, 0, op
->in
.access
, key_out
);
183 if(!NT_STATUS_IS_OK(hnd
->status
)) {
187 if(!op
->in
.parent_key
) {
188 /*then close the one that we opened above*/
189 hnd
->status
= rpccli_winreg_CloseKey( pipe_hnd
, mem_ctx
, parent_key
);
191 if(!NT_STATUS_IS_OK(hnd
->status
)) {
196 op
->out
.key
= key_out
;
201 int cac_RegEnumKeys(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegEnumKeys
*op
) {
202 struct rpc_pipe_client
*pipe_hnd
= NULL
;
204 /*buffers for rpccli_reg_enum_key call*/
206 fstring class_name_in
;
209 char **key_names_out
= NULL
;
210 char **class_names_out
= NULL
;
211 time_t *mod_times_out
= NULL
;
212 uint32 num_keys_out
= 0;
213 uint32 resume_idx
= 0;
218 /*this is to avoid useless rpc calls, if the last call exhausted all the keys, then we don't need to go through everything again*/
219 if(NT_STATUS_V(hnd
->status
) == NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED
))
222 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
223 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
227 if(!op
|| op
->in
.max_keys
== 0 || !mem_ctx
) {
228 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
232 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
234 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
238 /**the only way to know how many keys to expect is to assume max_keys keys will be found*/
239 key_names_out
= TALLOC_ARRAY(mem_ctx
, char *, op
->in
.max_keys
);
241 hnd
->status
= NT_STATUS_NO_MEMORY
;
245 class_names_out
= TALLOC_ARRAY(mem_ctx
, char *, op
->in
.max_keys
);
246 if(!class_names_out
) {
247 hnd
->status
= NT_STATUS_NO_MEMORY
;
248 TALLOC_FREE(key_names_out
);
252 mod_times_out
= TALLOC_ARRAY(mem_ctx
, time_t, op
->in
.max_keys
);
254 hnd
->status
= NT_STATUS_NO_MEMORY
;
255 TALLOC_FREE(key_names_out
);
256 TALLOC_FREE(class_names_out
);
261 resume_idx
= op
->out
.resume_idx
;
264 hnd
->status
= rpccli_winreg_enum_key( pipe_hnd
, mem_ctx
, op
->in
.key
, resume_idx
, key_name_in
, class_name_in
, &mod_times_out
[num_keys_out
]);
266 if(!NT_STATUS_IS_OK(hnd
->status
)) {
267 /*don't increment any values*/
271 key_names_out
[num_keys_out
] = talloc_strdup(mem_ctx
, key_name_in
);
273 class_names_out
[num_keys_out
] = talloc_strdup(mem_ctx
, class_name_in
);
275 if(!key_names_out
[num_keys_out
] || !class_names_out
[num_keys_out
]) {
276 hnd
->status
= NT_STATUS_NO_MEMORY
;
282 } while(num_keys_out
< op
->in
.max_keys
);
284 if(CAC_OP_FAILED(hnd
->status
)) {
285 op
->out
.num_keys
= 0;
289 op
->out
.resume_idx
= resume_idx
;
290 op
->out
.num_keys
= num_keys_out
;
291 op
->out
.key_names
= key_names_out
;
292 op
->out
.class_names
= class_names_out
;
293 op
->out
.mod_times
= mod_times_out
;
298 int cac_RegCreateKey(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegCreateKey
*op
) {
299 struct rpc_pipe_client
*pipe_hnd
= NULL
;
301 struct RegOpenKey rok
;
302 struct winreg_String key_string
, class_string
;
303 enum winreg_CreateAction action
= 0;
308 if(!hnd
->_internal
.ctx
) {
309 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
313 if(!op
|| !op
->in
.parent_key
|| !op
->in
.key_name
|| !mem_ctx
) {
314 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
318 /*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized*/
321 rok
.in
.name
= op
->in
.key_name
;
322 rok
.in
.access
= op
->in
.access
;
323 rok
.in
.parent_key
= op
->in
.parent_key
;
325 if(cac_RegOpenKey(hnd
, mem_ctx
, &rok
)) {
326 /*then we got the key, return*/
327 op
->out
.key
= rok
.out
.key
;
331 /*just be ultra-safe*/
332 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
334 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
338 key_out
= talloc(mem_ctx
, POLICY_HND
);
340 hnd
->status
= NT_STATUS_NO_MEMORY
;
344 key_string
.name
= op
->in
.key_name
;
345 class_string
.name
= op
->in
.class_name
;
346 hnd
->status
= rpccli_winreg_CreateKey( pipe_hnd
, mem_ctx
, op
->in
.parent_key
,
347 key_string
, class_string
, 0, op
->in
.access
, NULL
, key_out
, &action
);
349 if(!NT_STATUS_IS_OK(hnd
->status
)) {
353 op
->out
.key
= key_out
;
359 WERROR
cac_delete_subkeys_recursive(struct rpc_pipe_client
*pipe_hnd
, TALLOC_CTX
*mem_ctx
, POLICY_HND
*key
) {
360 /*NOTE: using cac functions might result in a big(ger) memory bloat, and would probably be far less efficient
361 * so we use the cli_reg functions directly*/
363 WERROR err
= WERR_OK
;
372 while(W_ERROR_IS_OK(err
)) {
373 struct winreg_String key_string
;
376 status
= rpccli_winreg_enum_key( pipe_hnd
, mem_ctx
, key
, cur_key
, subkey_name
, class_buf
, &mod_time_buf
);
378 if ( !NT_STATUS_IS_OK(status
) )
381 /*try to open the key with full access*/
382 key_string
.name
= subkey_name
;
383 status
= rpccli_winreg_OpenKey(pipe_hnd
, mem_ctx
, key
, key_string
, 0, REG_KEY_ALL
, &subkey
);
385 if ( !NT_STATUS_IS_OK(status
) )
388 err
= cac_delete_subkeys_recursive(pipe_hnd
, mem_ctx
, &subkey
);
390 if(!W_ERROR_EQUAL(err
,WERR_NO_MORE_ITEMS
) && !W_ERROR_IS_OK(err
))
393 /*flush the key just to be safe*/
394 rpccli_winreg_FlushKey(pipe_hnd
, mem_ctx
, key
);
396 /*close the key that we opened*/
397 rpccli_winreg_CloseKey(pipe_hnd
, mem_ctx
, &subkey
);
399 /*now we delete the subkey*/
400 key_string
.name
= subkey_name
;
401 status
= rpccli_winreg_DeleteKey(pipe_hnd
, mem_ctx
, key
, key_string
);
402 err
= ntstatus_to_werror(status
);
414 int cac_RegDeleteKey(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegDeleteKey
*op
) {
415 struct rpc_pipe_client
*pipe_hnd
= NULL
;
417 struct winreg_String key_string
;
422 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
423 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
427 if(!op
|| !op
->in
.parent_key
|| !op
->in
.name
|| !mem_ctx
) {
428 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
432 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
434 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
438 if(op
->in
.recursive
) {
439 /*first open the key, and then delete all of it's subkeys recursively*/
440 struct RegOpenKey rok
;
443 rok
.in
.parent_key
= op
->in
.parent_key
;
444 rok
.in
.name
= op
->in
.name
;
445 rok
.in
.access
= REG_KEY_ALL
;
447 if(!cac_RegOpenKey(hnd
, mem_ctx
, &rok
))
450 err
= cac_delete_subkeys_recursive(pipe_hnd
, mem_ctx
, rok
.out
.key
);
452 /*close the key that we opened*/
453 cac_RegClose(hnd
, mem_ctx
, rok
.out
.key
);
455 hnd
->status
= werror_to_ntstatus(err
);
457 if(NT_STATUS_V(hnd
->status
) != NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED
) && !NT_STATUS_IS_OK(hnd
->status
))
460 /*now go on to actually delete the key*/
463 key_string
.name
= op
->in
.name
;
464 hnd
->status
= rpccli_winreg_DeleteKey( pipe_hnd
, mem_ctx
, op
->in
.parent_key
, key_string
);
466 if(!NT_STATUS_IS_OK(hnd
->status
)) {
473 int cac_RegDeleteValue(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegDeleteValue
*op
) {
474 struct rpc_pipe_client
*pipe_hnd
= NULL
;
475 struct winreg_String value_string
;
480 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
481 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
485 if(!op
|| !op
->in
.parent_key
|| !op
->in
.name
|| !mem_ctx
) {
486 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
490 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
492 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
496 value_string
.name
= op
->in
.name
;
497 hnd
->status
= rpccli_winreg_DeleteValue( pipe_hnd
, mem_ctx
, op
->in
.parent_key
, value_string
);
499 if(!NT_STATUS_IS_OK(hnd
->status
)) {
507 /* JRA - disabled until fix. */
508 /* This code is currently broken so disable it - it needs to handle the ERROR_MORE_DATA
509 cleanly and resubmit the query. */
511 int cac_RegQueryKeyInfo(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegQueryKeyInfo
*op
) {
512 struct rpc_pipe_client
*pipe_hnd
= NULL
;
515 char *class_name_out
= NULL
;
516 uint32 class_len
= 0;
517 uint32 num_subkeys_out
= 0;
518 uint32 long_subkey_out
= 0;
519 uint32 long_class_out
= 0;
520 uint32 num_values_out
= 0;
521 uint32 long_value_out
= 0;
522 uint32 long_data_out
= 0;
523 uint32 secdesc_size
= 0;
529 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
530 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
534 if(!op
|| !op
->in
.key
|| !mem_ctx
) {
535 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
539 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
541 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
545 err
= rpccli_reg_query_key( pipe_hnd
, mem_ctx
, op
->in
.key
,
557 hnd
->status
= werror_to_ntstatus(err
);
559 if(!NT_STATUS_IS_OK(hnd
->status
))
562 if(!class_name_out
) {
563 op
->out
.class_name
= talloc_strdup(mem_ctx
, "");
565 else if(class_len
!= 0 && class_name_out
[class_len
- 1] != '\0') {
566 /*then we need to add a '\0'*/
567 op
->out
.class_name
= talloc_size(mem_ctx
, sizeof(char)*(class_len
+ 1));
569 memcpy(op
->out
.class_name
, class_name_out
, class_len
);
571 op
->out
.class_name
[class_len
] = '\0';
573 else { /*then everything worked out fine in the function*/
574 op
->out
.class_name
= talloc_strdup(mem_ctx
, class_name_out
);
577 if(!op
->out
.class_name
) {
578 hnd
->status
= NT_STATUS_NO_MEMORY
;
582 op
->out
.num_subkeys
= num_subkeys_out
;
583 op
->out
.longest_subkey
= long_subkey_out
;
584 op
->out
.longest_class
= long_class_out
;
585 op
->out
.num_values
= num_values_out
;
586 op
->out
.longest_value_name
= long_value_out
;
587 op
->out
.longest_value_data
= long_data_out
;
588 op
->out
.security_desc_size
= secdesc_size
;
589 op
->out
.last_write_time
= nt_time_to_unix(&mod_time
);
595 int cac_RegQueryValue(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegQueryValue
*op
) {
596 struct rpc_pipe_client
*pipe_hnd
= NULL
;
597 struct winreg_String value_string
;
598 REGVAL_BUFFER buffer
;
599 REG_VALUE_DATA
*data_out
= NULL
;
600 enum winreg_Type val_type
;
602 uint32 buf_size
= 4096;
608 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
609 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
613 if(!op
|| !op
->in
.key
|| !op
->in
.val_name
|| !mem_ctx
) {
614 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
618 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
620 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
624 value_string
.name
= op
->in
.val_name
;
626 if ( (buf
= TALLOC_ARRAY( mem_ctx
, uint8
, buf_size
)) == NULL
) {
627 hnd
->status
= NT_STATUS_NO_MEMORY
;
631 hnd
->status
= rpccli_winreg_QueryValue(pipe_hnd
, mem_ctx
, op
->in
.key
,
632 value_string
, &val_type
, buf
, &buf_size
, &length
);
634 if(!NT_STATUS_IS_OK(hnd
->status
))
637 init_regval_buffer( &buffer
, buf
, length
);
639 data_out
= cac_MakeRegValueData(mem_ctx
, val_type
, buffer
);
642 hnd
->status
= NT_STATUS_NO_MEMORY
;
644 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
649 op
->out
.type
= val_type
;
650 op
->out
.data
= data_out
;
656 int cac_RegEnumValues(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegEnumValues
*op
) {
657 struct rpc_pipe_client
*pipe_hnd
= NULL
;
659 /*buffers for rpccli_reg_enum_key call*/
660 fstring val_name_buf
;
661 REGVAL_BUFFER val_buf
;
664 uint32
*types_out
= NULL
;
665 REG_VALUE_DATA
**values_out
= NULL
;
666 char **val_names_out
= NULL
;
667 uint32 num_values_out
= 0;
668 uint32 resume_idx
= 0;
673 /*this is to avoid useless rpc calls, if the last call exhausted all the keys, then we don't need to go through everything again*/
674 if(NT_STATUS_V(hnd
->status
) == NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED
))
677 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
678 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
682 if(!op
|| !op
->in
.key
|| op
->in
.max_values
== 0 || !mem_ctx
) {
683 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
687 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
689 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
693 /*we need to assume that the max number of values will be enumerated*/
694 types_out
= (uint32
*)talloc_array(mem_ctx
, int, op
->in
.max_values
);
696 hnd
->status
= NT_STATUS_NO_MEMORY
;
700 values_out
= talloc_array(mem_ctx
, REG_VALUE_DATA
*, op
->in
.max_values
);
702 TALLOC_FREE(types_out
);
703 hnd
->status
= NT_STATUS_NO_MEMORY
;
707 val_names_out
= talloc_array(mem_ctx
, char *, op
->in
.max_values
);
709 TALLOC_FREE(types_out
);
710 TALLOC_FREE(values_out
);
711 hnd
->status
= NT_STATUS_NO_MEMORY
;
715 resume_idx
= op
->out
.resume_idx
;
717 ZERO_STRUCT(val_buf
);
719 hnd
->status
= rpccli_winreg_enum_val(pipe_hnd
, mem_ctx
, op
->in
.key
, resume_idx
, val_name_buf
, &types_out
[num_values_out
], &val_buf
);
721 if(!NT_STATUS_IS_OK(hnd
->status
))
724 values_out
[num_values_out
] = cac_MakeRegValueData(mem_ctx
, types_out
[num_values_out
], val_buf
);
725 val_names_out
[num_values_out
] = talloc_strdup(mem_ctx
, val_name_buf
);
727 if(!val_names_out
[num_values_out
] || !values_out
[num_values_out
]) {
728 hnd
->status
= NT_STATUS_NO_MEMORY
;
734 } while(num_values_out
< op
->in
.max_values
);
736 if(CAC_OP_FAILED(hnd
->status
))
739 op
->out
.types
= types_out
;
740 op
->out
.num_values
= num_values_out
;
741 op
->out
.value_names
= val_names_out
;
742 op
->out
.values
= values_out
;
743 op
->out
.resume_idx
= resume_idx
;
748 int cac_RegSetValue(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegSetValue
*op
) {
749 struct rpc_pipe_client
*pipe_hnd
= NULL
;
750 struct winreg_String value_string
;
752 RPC_DATA_BLOB
*buffer
;
757 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
758 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
762 if(!op
|| !op
->in
.key
|| !op
->in
.val_name
|| !mem_ctx
) {
763 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
767 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
769 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
773 buffer
= cac_MakeRpcDataBlob(mem_ctx
, op
->in
.type
, op
->in
.value
);
777 hnd
->status
= NT_STATUS_NO_MEMORY
;
779 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
784 value_string
.name
= op
->in
.val_name
;
785 hnd
->status
= rpccli_winreg_SetValue(pipe_hnd
, mem_ctx
, op
->in
.key
, value_string
, op
->in
.type
, buffer
->buffer
, buffer
->buf_len
);
787 if(!NT_STATUS_IS_OK(hnd
->status
))
791 hnd
->status
= rpccli_winreg_FlushKey(pipe_hnd
, mem_ctx
, op
->in
.key
);
793 if(!NT_STATUS_IS_OK(hnd
->status
))
801 int cac_RegGetVersion(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegGetVersion
*op
) {
802 struct rpc_pipe_client
*pipe_hnd
= NULL
;
808 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
809 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
813 if(!op
|| !op
->in
.key
|| !mem_ctx
) {
814 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
818 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
820 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
824 hnd
->status
= rpccli_winreg_GetVersion( pipe_hnd
, mem_ctx
, op
->in
.key
, &version_out
);
826 if(!NT_STATUS_IS_OK(hnd
->status
))
829 op
->out
.version
= version_out
;
834 int cac_RegGetKeySecurity(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegGetKeySecurity
*op
) {
835 struct rpc_pipe_client
*pipe_hnd
= NULL
;
836 struct KeySecurityData keysec
;
843 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
844 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
848 if(!op
|| !op
->in
.key
|| op
->in
.info_type
== 0 || !mem_ctx
) {
849 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
853 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
855 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
859 hnd
->status
= rpccli_winreg_GetKeySecurity(pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.info_type
, &keysec
);
861 if(!NT_STATUS_IS_OK(hnd
->status
)) {
865 #if 0 /* FIX ME!!!! unmarshall the security descriptor */
866 op
->out
.size
= buf
.sd_size
;
867 op
->out
.descriptor
= dup_sec_desc(mem_ctx
, buf
.sd
);
870 if (op
->out
.descriptor
== NULL
) {
877 int cac_RegSetKeySecurity(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegSetKeySecurity
*op
) {
878 struct rpc_pipe_client
*pipe_hnd
= NULL
;
879 struct KeySecurityData keysec
;
881 ZERO_STRUCT( keysec
);
886 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
887 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
891 if(!op
|| !op
->in
.key
|| op
->in
.info_type
== 0 || op
->in
.size
== 0 || !op
->in
.descriptor
|| !mem_ctx
) {
892 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
896 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
898 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
902 /* FIXME!!! Marshall in the input sec_desc to struct KeySecurityData */
903 hnd
->status
= rpccli_winreg_SetKeySecurity(pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.info_type
, &keysec
);
905 if(!NT_STATUS_IS_OK(hnd
->status
)) {
912 int cac_Shutdown(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct Shutdown
*op
) {
914 struct rpc_pipe_client
*pipe_hnd
= NULL
;
915 struct initshutdown_String msg_string
;
916 struct initshutdown_String_sub s
;
923 if(!hnd
->_internal
.ctx
) {
924 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
928 if(!op
|| !mem_ctx
) {
929 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
933 srv
= cac_GetServer(hnd
);
935 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
939 /*initialize for winreg pipe if we have to*/
940 if(!hnd
->_internal
.pipes
[PI_INITSHUTDOWN
]) {
941 if(!(pipe_hnd
= cli_rpc_pipe_open_noauth(srv
->cli
, PI_INITSHUTDOWN
, &(hnd
->status
)))) {
945 hnd
->_internal
.pipes
[PI_INITSHUTDOWN
] = True
;
948 pipe_hnd
= cac_GetPipe(hnd
, PI_INITSHUTDOWN
);
950 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
954 msg
= (op
->in
.message
!= NULL
) ? op
->in
.message
: talloc_strdup(mem_ctx
, "");
955 msg_string
.name
= &s
;
956 msg_string
.name
->name
= msg
;
958 hnd
->status
= NT_STATUS_OK
;
960 if(hnd
->_internal
.srv_level
> SRV_WIN_NT4
) {
961 hnd
->status
= rpccli_initshutdown_InitEx( pipe_hnd
, mem_ctx
, NULL
, &msg_string
,
962 op
->in
.timeout
, op
->in
.reboot
, op
->in
.force
, op
->in
.reason
);
965 if(hnd
->_internal
.srv_level
< SRV_WIN_2K
|| !NT_STATUS_IS_OK(hnd
->status
)) {
966 hnd
->status
= rpccli_initshutdown_Init( pipe_hnd
, mem_ctx
, NULL
, &msg_string
,
967 op
->in
.timeout
, op
->in
.reboot
, op
->in
.force
);
969 hnd
->_internal
.srv_level
= SRV_WIN_NT4
;
972 if(!NT_STATUS_IS_OK(hnd
->status
)) {
979 int cac_AbortShutdown(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
) {
980 struct rpc_pipe_client
*pipe_hnd
= NULL
;
985 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_INITSHUTDOWN
]) {
986 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
990 pipe_hnd
= cac_GetPipe(hnd
, PI_INITSHUTDOWN
);
992 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
996 hnd
->status
= rpccli_initshutdown_Abort(pipe_hnd
, mem_ctx
, NULL
);
998 if(!NT_STATUS_IS_OK(hnd
->status
))