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
;
34 if(!hnd
->_internal
.ctx
) {
35 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
39 if(!op
|| !op
->in
.root
|| !mem_ctx
) {
40 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
44 srv
= cac_GetServer(hnd
);
46 hnd
->status
= NT_STATUS_INVALID_CONNECTION
;
50 /*initialize for winreg pipe if we have to*/
51 if(!hnd
->_internal
.pipes
[PI_WINREG
]) {
52 if(!(pipe_hnd
= cli_rpc_pipe_open_noauth(&srv
->cli
, PI_WINREG
, &(hnd
->status
)))) {
56 hnd
->_internal
.pipes
[PI_WINREG
] = True
;
59 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
61 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
65 key
= talloc(mem_ctx
, POLICY_HND
);
67 hnd
->status
= NT_STATUS_NO_MEMORY
;
70 err
= rpccli_reg_connect( pipe_hnd
, mem_ctx
, op
->in
.root
, op
->in
.access
, key
);
71 hnd
->status
= werror_to_ntstatus(err
);
73 if(!NT_STATUS_IS_OK(hnd
->status
)) {
82 int cac_RegClose(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, POLICY_HND
*key
) {
83 struct rpc_pipe_client
*pipe_hnd
= NULL
;
89 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
90 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
94 if(!key
|| !mem_ctx
) {
95 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
99 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
101 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
105 err
= rpccli_reg_close(pipe_hnd
, mem_ctx
, key
);
106 hnd
->status
= werror_to_ntstatus(err
);
108 if(!NT_STATUS_IS_OK(hnd
->status
)) {
115 int cac_RegOpenKey(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegOpenKey
*op
) {
116 struct rpc_pipe_client
*pipe_hnd
= NULL
;
120 POLICY_HND
*parent_key
;
122 char *key_name
= NULL
;
125 struct RegConnect rc
;
130 if(!hnd
->_internal
.ctx
) {
131 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
135 if(!op
|| !op
->in
.name
|| !mem_ctx
) {
136 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
141 key_out
= talloc(mem_ctx
, POLICY_HND
);
143 hnd
->status
= NT_STATUS_NO_MEMORY
;
147 if(!op
->in
.parent_key
) {
148 /*then we need to connect to the registry*/
149 if(!cac_ParseRegPath(op
->in
.name
, ®_type
, &key_name
)) {
150 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
154 /*use cac_RegConnect because it handles the session setup*/
157 rc
.in
.access
= op
->in
.access
;
158 rc
.in
.root
= reg_type
;
160 if(!cac_RegConnect(hnd
, mem_ctx
, &rc
)) {
164 /**if they only specified the root key, return the key we just opened*/
165 if(key_name
== NULL
) {
166 op
->out
.key
= rc
.out
.key
;
170 parent_key
= rc
.out
.key
;
173 parent_key
= op
->in
.parent_key
;
174 key_name
= op
->in
.name
;
177 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
179 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
183 err
= rpccli_reg_open_entry( pipe_hnd
, mem_ctx
, parent_key
, key_name
, op
->in
.access
, key_out
);
184 hnd
->status
= werror_to_ntstatus(err
);
186 if(!NT_STATUS_IS_OK(hnd
->status
)) {
190 if(!op
->in
.parent_key
) {
191 /*then close the one that we opened above*/
192 err
= rpccli_reg_close( pipe_hnd
, mem_ctx
, parent_key
);
193 hnd
->status
= werror_to_ntstatus(err
);
195 if(!NT_STATUS_IS_OK(hnd
->status
)) {
200 op
->out
.key
= key_out
;
205 int cac_RegEnumKeys(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegEnumKeys
*op
) {
206 struct rpc_pipe_client
*pipe_hnd
= NULL
;
209 /*buffers for rpccli_reg_enum_key call*/
211 fstring class_name_in
;
214 char **key_names_out
= NULL
;
215 char **class_names_out
= NULL
;
216 time_t *mod_times_out
= NULL
;
217 uint32 num_keys_out
= 0;
218 uint32 resume_idx
= 0;
223 /*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*/
224 if(NT_STATUS_V(hnd
->status
) == NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED
))
227 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
228 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
232 if(!op
|| op
->in
.max_keys
== 0 || !mem_ctx
) {
233 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
237 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
239 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
243 /**the only way to know how many keys to expect is to assume max_keys keys will be found*/
244 key_names_out
= TALLOC_ARRAY(mem_ctx
, char *, op
->in
.max_keys
);
246 hnd
->status
= NT_STATUS_NO_MEMORY
;
250 class_names_out
= TALLOC_ARRAY(mem_ctx
, char *, op
->in
.max_keys
);
251 if(!class_names_out
) {
252 hnd
->status
= NT_STATUS_NO_MEMORY
;
253 TALLOC_FREE(key_names_out
);
257 mod_times_out
= TALLOC_ARRAY(mem_ctx
, time_t, op
->in
.max_keys
);
259 hnd
->status
= NT_STATUS_NO_MEMORY
;
260 TALLOC_FREE(key_names_out
);
261 TALLOC_FREE(class_names_out
);
266 resume_idx
= op
->out
.resume_idx
;
269 err
= rpccli_reg_enum_key( pipe_hnd
, mem_ctx
, op
->in
.key
, resume_idx
, key_name_in
, class_name_in
, &mod_times_out
[num_keys_out
]);
270 hnd
->status
= werror_to_ntstatus(err
);
272 if(!NT_STATUS_IS_OK(hnd
->status
)) {
273 /*don't increment any values*/
277 key_names_out
[num_keys_out
] = talloc_strdup(mem_ctx
, key_name_in
);
279 class_names_out
[num_keys_out
] = talloc_strdup(mem_ctx
, class_name_in
);
281 if(!key_names_out
[num_keys_out
] || !class_names_out
[num_keys_out
]) {
282 hnd
->status
= NT_STATUS_NO_MEMORY
;
288 } while(num_keys_out
< op
->in
.max_keys
);
290 if(CAC_OP_FAILED(hnd
->status
)) {
291 op
->out
.num_keys
= 0;
295 op
->out
.resume_idx
= resume_idx
;
296 op
->out
.num_keys
= num_keys_out
;
297 op
->out
.key_names
= key_names_out
;
298 op
->out
.class_names
= class_names_out
;
299 op
->out
.mod_times
= mod_times_out
;
304 int cac_RegCreateKey(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegCreateKey
*op
) {
305 struct rpc_pipe_client
*pipe_hnd
= NULL
;
310 struct RegOpenKey rok
;
315 if(!hnd
->_internal
.ctx
) {
316 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
320 if(!op
|| !op
->in
.parent_key
|| !op
->in
.key_name
|| !mem_ctx
) {
321 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
325 /*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized*/
328 rok
.in
.name
= op
->in
.key_name
;
329 rok
.in
.access
= op
->in
.access
;
330 rok
.in
.parent_key
= op
->in
.parent_key
;
332 if(cac_RegOpenKey(hnd
, mem_ctx
, &rok
)) {
333 /*then we got the key, return*/
334 op
->out
.key
= rok
.out
.key
;
338 /*just be ultra-safe*/
339 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
341 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
345 key_out
= talloc(mem_ctx
, POLICY_HND
);
347 hnd
->status
= NT_STATUS_NO_MEMORY
;
351 err
= rpccli_reg_create_key_ex( pipe_hnd
, mem_ctx
, op
->in
.parent_key
, op
->in
.key_name
, op
->in
.class_name
, op
->in
.access
, key_out
);
352 hnd
->status
= werror_to_ntstatus(err
);
354 if(!NT_STATUS_IS_OK(hnd
->status
)) {
358 op
->out
.key
= key_out
;
364 WERROR
cac_delete_subkeys_recursive(struct rpc_pipe_client
*pipe_hnd
, TALLOC_CTX
*mem_ctx
, POLICY_HND
*key
) {
365 /*NOTE: using cac functions might result in a big(ger) memory bloat, and would probably be far less efficient
366 * so we use the cli_reg functions directly*/
368 WERROR err
= WERR_OK
;
377 while(W_ERROR_IS_OK(err
)) {
378 err
= rpccli_reg_enum_key( pipe_hnd
, mem_ctx
, key
, cur_key
, subkey_name
, class_buf
, &mod_time_buf
);
380 if(!W_ERROR_IS_OK(err
))
383 /*try to open the key with full access*/
384 err
= rpccli_reg_open_entry(pipe_hnd
, mem_ctx
, key
, subkey_name
, REG_KEY_ALL
, &subkey
);
386 if(!W_ERROR_IS_OK(err
))
389 err
= cac_delete_subkeys_recursive(pipe_hnd
, mem_ctx
, &subkey
);
391 if(!W_ERROR_EQUAL(err
,WERR_NO_MORE_ITEMS
) && !W_ERROR_IS_OK(err
))
394 /*flush the key just to be safe*/
395 rpccli_reg_flush_key(pipe_hnd
, mem_ctx
, key
);
397 /*close the key that we opened*/
398 rpccli_reg_close(pipe_hnd
, mem_ctx
, &subkey
);
400 /*now we delete the subkey*/
401 err
= rpccli_reg_delete_key(pipe_hnd
, mem_ctx
, key
, subkey_name
);
413 int cac_RegDeleteKey(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegDeleteKey
*op
) {
414 struct rpc_pipe_client
*pipe_hnd
= NULL
;
420 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
421 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
425 if(!op
|| !op
->in
.parent_key
|| !op
->in
.name
|| !mem_ctx
) {
426 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
430 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
432 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
436 if(op
->in
.recursive
) {
437 /*first open the key, and then delete all of it's subkeys recursively*/
438 struct RegOpenKey rok
;
441 rok
.in
.parent_key
= op
->in
.parent_key
;
442 rok
.in
.name
= op
->in
.name
;
443 rok
.in
.access
= REG_KEY_ALL
;
445 if(!cac_RegOpenKey(hnd
, mem_ctx
, &rok
))
448 err
= cac_delete_subkeys_recursive(pipe_hnd
, mem_ctx
, rok
.out
.key
);
450 /*close the key that we opened*/
451 cac_RegClose(hnd
, mem_ctx
, rok
.out
.key
);
453 hnd
->status
= werror_to_ntstatus(err
);
455 if(NT_STATUS_V(hnd
->status
) != NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED
) && !NT_STATUS_IS_OK(hnd
->status
))
458 /*now go on to actually delete the key*/
461 err
= rpccli_reg_delete_key( pipe_hnd
, mem_ctx
, op
->in
.parent_key
, op
->in
.name
);
462 hnd
->status
= werror_to_ntstatus(err
);
464 if(!NT_STATUS_IS_OK(hnd
->status
)) {
471 int cac_RegDeleteValue(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegDeleteValue
*op
) {
472 struct rpc_pipe_client
*pipe_hnd
= NULL
;
478 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
479 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
483 if(!op
|| !op
->in
.parent_key
|| !op
->in
.name
|| !mem_ctx
) {
484 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
488 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
490 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
494 err
= rpccli_reg_delete_val( pipe_hnd
, mem_ctx
, op
->in
.parent_key
, op
->in
.name
);
495 hnd
->status
= werror_to_ntstatus(err
);
497 if(!NT_STATUS_IS_OK(hnd
->status
)) {
505 /* JRA - disabled until fix. */
506 /* This code is currently broken so disable it - it needs to handle the ERROR_MORE_DATA
507 cleanly and resubmit the query. */
509 int cac_RegQueryKeyInfo(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegQueryKeyInfo
*op
) {
510 struct rpc_pipe_client
*pipe_hnd
= NULL
;
513 char *class_name_out
= NULL
;
514 uint32 class_len
= 0;
515 uint32 num_subkeys_out
= 0;
516 uint32 long_subkey_out
= 0;
517 uint32 long_class_out
= 0;
518 uint32 num_values_out
= 0;
519 uint32 long_value_out
= 0;
520 uint32 long_data_out
= 0;
521 uint32 secdesc_size
= 0;
527 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
528 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
532 if(!op
|| !op
->in
.key
|| !mem_ctx
) {
533 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
537 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
539 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
543 err
= rpccli_reg_query_key( pipe_hnd
, mem_ctx
, op
->in
.key
,
555 hnd
->status
= werror_to_ntstatus(err
);
557 if(!NT_STATUS_IS_OK(hnd
->status
))
560 if(!class_name_out
) {
561 op
->out
.class_name
= talloc_strdup(mem_ctx
, "");
563 else if(class_len
!= 0 && class_name_out
[class_len
- 1] != '\0') {
564 /*then we need to add a '\0'*/
565 op
->out
.class_name
= talloc_size(mem_ctx
, sizeof(char)*(class_len
+ 1));
567 memcpy(op
->out
.class_name
, class_name_out
, class_len
);
569 op
->out
.class_name
[class_len
] = '\0';
571 else { /*then everything worked out fine in the function*/
572 op
->out
.class_name
= talloc_strdup(mem_ctx
, class_name_out
);
575 if(!op
->out
.class_name
) {
576 hnd
->status
= NT_STATUS_NO_MEMORY
;
580 op
->out
.num_subkeys
= num_subkeys_out
;
581 op
->out
.longest_subkey
= long_subkey_out
;
582 op
->out
.longest_class
= long_class_out
;
583 op
->out
.num_values
= num_values_out
;
584 op
->out
.longest_value_name
= long_value_out
;
585 op
->out
.longest_value_data
= long_data_out
;
586 op
->out
.security_desc_size
= secdesc_size
;
587 op
->out
.last_write_time
= nt_time_to_unix(&mod_time
);
593 int cac_RegQueryValue(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegQueryValue
*op
) {
594 struct rpc_pipe_client
*pipe_hnd
= NULL
;
598 REGVAL_BUFFER buffer
;
599 REG_VALUE_DATA
*data_out
= NULL
;
604 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
605 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
609 if(!op
|| !op
->in
.key
|| !op
->in
.val_name
|| !mem_ctx
) {
610 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
614 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
616 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
620 err
= rpccli_reg_query_value(pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.val_name
, &val_type
, &buffer
);
621 hnd
->status
= werror_to_ntstatus(err
);
623 if(!NT_STATUS_IS_OK(hnd
->status
))
626 data_out
= cac_MakeRegValueData(mem_ctx
, val_type
, buffer
);
629 hnd
->status
= NT_STATUS_NO_MEMORY
;
631 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
636 op
->out
.type
= val_type
;
637 op
->out
.data
= data_out
;
643 int cac_RegEnumValues(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegEnumValues
*op
) {
644 struct rpc_pipe_client
*pipe_hnd
= NULL
;
647 /*buffers for rpccli_reg_enum_key call*/
648 fstring val_name_buf
;
649 REGVAL_BUFFER val_buf
;
652 uint32
*types_out
= NULL
;
653 REG_VALUE_DATA
**values_out
= NULL
;
654 char **val_names_out
= NULL
;
655 uint32 num_values_out
= 0;
656 uint32 resume_idx
= 0;
661 /*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*/
662 if(NT_STATUS_V(hnd
->status
) == NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED
))
665 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
666 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
670 if(!op
|| !op
->in
.key
|| op
->in
.max_values
== 0 || !mem_ctx
) {
671 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
675 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
677 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
681 /*we need to assume that the max number of values will be enumerated*/
682 types_out
= (uint32
*)talloc_array(mem_ctx
, int, op
->in
.max_values
);
684 hnd
->status
= NT_STATUS_NO_MEMORY
;
688 values_out
= talloc_array(mem_ctx
, REG_VALUE_DATA
*, op
->in
.max_values
);
690 TALLOC_FREE(types_out
);
691 hnd
->status
= NT_STATUS_NO_MEMORY
;
695 val_names_out
= talloc_array(mem_ctx
, char *, op
->in
.max_values
);
697 TALLOC_FREE(types_out
);
698 TALLOC_FREE(values_out
);
699 hnd
->status
= NT_STATUS_NO_MEMORY
;
703 resume_idx
= op
->out
.resume_idx
;
705 ZERO_STRUCT(val_buf
);
707 err
= rpccli_reg_enum_val(pipe_hnd
, mem_ctx
, op
->in
.key
, resume_idx
, val_name_buf
, &types_out
[num_values_out
], &val_buf
);
708 hnd
->status
= werror_to_ntstatus(err
);
710 if(!NT_STATUS_IS_OK(hnd
->status
))
713 values_out
[num_values_out
] = cac_MakeRegValueData(mem_ctx
, types_out
[num_values_out
], val_buf
);
714 val_names_out
[num_values_out
] = talloc_strdup(mem_ctx
, val_name_buf
);
716 if(!val_names_out
[num_values_out
] || !values_out
[num_values_out
]) {
717 hnd
->status
= NT_STATUS_NO_MEMORY
;
723 } while(num_values_out
< op
->in
.max_values
);
725 if(CAC_OP_FAILED(hnd
->status
))
728 op
->out
.types
= types_out
;
729 op
->out
.num_values
= num_values_out
;
730 op
->out
.value_names
= val_names_out
;
731 op
->out
.values
= values_out
;
732 op
->out
.resume_idx
= resume_idx
;
737 int cac_RegSetValue(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegSetValue
*op
) {
738 struct rpc_pipe_client
*pipe_hnd
= NULL
;
741 RPC_DATA_BLOB
*buffer
;
746 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
747 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
751 if(!op
|| !op
->in
.key
|| !op
->in
.val_name
|| !mem_ctx
) {
752 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
756 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
758 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
762 buffer
= cac_MakeRpcDataBlob(mem_ctx
, op
->in
.type
, op
->in
.value
);
766 hnd
->status
= NT_STATUS_NO_MEMORY
;
768 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
773 err
= rpccli_reg_set_val(pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.val_name
, op
->in
.type
, buffer
);
774 hnd
->status
= werror_to_ntstatus(err
);
776 if(!NT_STATUS_IS_OK(hnd
->status
))
780 err
= rpccli_reg_flush_key(pipe_hnd
, mem_ctx
, op
->in
.key
);
781 hnd
->status
= werror_to_ntstatus(err
);
783 if(!NT_STATUS_IS_OK(hnd
->status
))
791 int cac_RegGetVersion(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegGetVersion
*op
) {
792 struct rpc_pipe_client
*pipe_hnd
= NULL
;
800 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
801 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
805 if(!op
|| !op
->in
.key
|| !mem_ctx
) {
806 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
810 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
812 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
816 err
= rpccli_reg_getversion( pipe_hnd
, mem_ctx
, op
->in
.key
, &version_out
);
817 hnd
->status
= werror_to_ntstatus(err
);
819 if(!NT_STATUS_IS_OK(hnd
->status
))
822 op
->out
.version
= version_out
;
827 int cac_RegGetKeySecurity(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegGetKeySecurity
*op
) {
828 struct rpc_pipe_client
*pipe_hnd
= NULL
;
839 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
840 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
844 if(!op
|| !op
->in
.key
|| op
->in
.info_type
== 0 || !mem_ctx
) {
845 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
849 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
851 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
855 err
= rpccli_reg_get_key_sec(pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.info_type
, &buf_size
, &buf
);
856 hnd
->status
= werror_to_ntstatus(err
);
859 if(!NT_STATUS_IS_OK(hnd
->status
)) {
863 op
->out
.size
= buf
.len
;
864 op
->out
.descriptor
= dup_sec_desc(mem_ctx
, buf
.sec
);
866 if (op
->out
.descriptor
== NULL
) {
873 int cac_RegSetKeySecurity(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegSetKeySecurity
*op
) {
874 struct rpc_pipe_client
*pipe_hnd
= NULL
;
880 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
881 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
885 if(!op
|| !op
->in
.key
|| op
->in
.info_type
== 0 || op
->in
.size
== 0 || !op
->in
.descriptor
|| !mem_ctx
) {
886 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
890 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
892 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
896 err
= rpccli_reg_set_key_sec(pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.info_type
, op
->in
.size
, op
->in
.descriptor
);
897 hnd
->status
= werror_to_ntstatus(err
);
900 if(!NT_STATUS_IS_OK(hnd
->status
)) {
907 int cac_RegSaveKey(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegSaveKey
*op
) {
908 struct rpc_pipe_client
*pipe_hnd
= NULL
;
914 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
915 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
919 if(!op
|| !op
->in
.key
|| !op
->in
.filename
|| !mem_ctx
) {
920 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
924 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
926 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
930 err
= rpccli_reg_save_key( pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.filename
);
931 hnd
->status
= werror_to_ntstatus(err
);
934 if(!NT_STATUS_IS_OK(hnd
->status
)) {
941 int cac_Shutdown(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct Shutdown
*op
) {
943 struct rpc_pipe_client
*pipe_hnd
= NULL
;
950 if(!hnd
->_internal
.ctx
) {
951 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
955 if(!op
|| !mem_ctx
) {
956 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
960 srv
= cac_GetServer(hnd
);
962 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
966 /*initialize for winreg pipe if we have to*/
967 if(!hnd
->_internal
.pipes
[PI_SHUTDOWN
]) {
968 if(!(pipe_hnd
= cli_rpc_pipe_open_noauth(&srv
->cli
, PI_SHUTDOWN
, &(hnd
->status
)))) {
972 hnd
->_internal
.pipes
[PI_SHUTDOWN
] = True
;
975 pipe_hnd
= cac_GetPipe(hnd
, PI_SHUTDOWN
);
977 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
981 msg
= (op
->in
.message
!= NULL
) ? op
->in
.message
: talloc_strdup(mem_ctx
, "");
983 hnd
->status
= NT_STATUS_OK
;
985 if(hnd
->_internal
.srv_level
> SRV_WIN_NT4
) {
986 hnd
->status
= rpccli_shutdown_init_ex( pipe_hnd
, mem_ctx
, msg
, op
->in
.timeout
, op
->in
.reboot
, op
->in
.force
, op
->in
.reason
);
989 if(hnd
->_internal
.srv_level
< SRV_WIN_2K
|| !NT_STATUS_IS_OK(hnd
->status
)) {
990 hnd
->status
= rpccli_shutdown_init( pipe_hnd
, mem_ctx
, msg
, op
->in
.timeout
, op
->in
.reboot
, op
->in
.force
);
992 hnd
->_internal
.srv_level
= SRV_WIN_NT4
;
995 if(!NT_STATUS_IS_OK(hnd
->status
)) {
1002 int cac_AbortShutdown(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
) {
1003 struct rpc_pipe_client
*pipe_hnd
= NULL
;
1008 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_SHUTDOWN
]) {
1009 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1013 pipe_hnd
= cac_GetPipe(hnd
, PI_SHUTDOWN
);
1015 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1019 hnd
->status
= rpccli_shutdown_abort(pipe_hnd
, mem_ctx
);
1021 if(!NT_STATUS_IS_OK(hnd
->status
))