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
)) {
504 int cac_RegQueryKeyInfo(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegQueryKeyInfo
*op
) {
505 struct rpc_pipe_client
*pipe_hnd
= NULL
;
508 char *class_name_out
= NULL
;
509 uint32 class_len
= 0;
510 uint32 num_subkeys_out
= 0;
511 uint32 long_subkey_out
= 0;
512 uint32 long_class_out
= 0;
513 uint32 num_values_out
= 0;
514 uint32 long_value_out
= 0;
515 uint32 long_data_out
= 0;
516 uint32 secdesc_size
= 0;
522 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
523 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
527 if(!op
|| !op
->in
.key
|| !mem_ctx
) {
528 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
532 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
534 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
538 err
= rpccli_reg_query_key( pipe_hnd
, mem_ctx
, op
->in
.key
,
550 hnd
->status
= werror_to_ntstatus(err
);
552 if(!NT_STATUS_IS_OK(hnd
->status
))
555 if(!class_name_out
) {
556 op
->out
.class_name
= talloc_strdup(mem_ctx
, "");
558 else if(class_len
!= 0 && class_name_out
[class_len
- 1] != '\0') {
559 /*then we need to add a '\0'*/
560 op
->out
.class_name
= talloc_size(mem_ctx
, sizeof(char)*(class_len
+ 1));
562 memcpy(op
->out
.class_name
, class_name_out
, class_len
);
564 op
->out
.class_name
[class_len
] = '\0';
566 else { /*then everything worked out fine in the function*/
567 op
->out
.class_name
= talloc_strdup(mem_ctx
, class_name_out
);
570 if(!op
->out
.class_name
) {
571 hnd
->status
= NT_STATUS_NO_MEMORY
;
575 op
->out
.num_subkeys
= num_subkeys_out
;
576 op
->out
.longest_subkey
= long_subkey_out
;
577 op
->out
.longest_class
= long_class_out
;
578 op
->out
.num_values
= num_values_out
;
579 op
->out
.longest_value_name
= long_value_out
;
580 op
->out
.longest_value_data
= long_data_out
;
581 op
->out
.security_desc_size
= secdesc_size
;
582 op
->out
.last_write_time
= nt_time_to_unix(&mod_time
);
587 int cac_RegQueryValue(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegQueryValue
*op
) {
588 struct rpc_pipe_client
*pipe_hnd
= NULL
;
592 REGVAL_BUFFER buffer
;
593 REG_VALUE_DATA
*data_out
= NULL
;
598 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
599 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
603 if(!op
|| !op
->in
.key
|| !op
->in
.val_name
|| !mem_ctx
) {
604 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
608 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
610 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
614 err
= rpccli_reg_query_value(pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.val_name
, &val_type
, &buffer
);
615 hnd
->status
= werror_to_ntstatus(err
);
617 if(!NT_STATUS_IS_OK(hnd
->status
))
620 data_out
= cac_MakeRegValueData(mem_ctx
, val_type
, buffer
);
623 hnd
->status
= NT_STATUS_NO_MEMORY
;
625 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
630 op
->out
.type
= val_type
;
631 op
->out
.data
= data_out
;
637 int cac_RegEnumValues(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegEnumValues
*op
) {
638 struct rpc_pipe_client
*pipe_hnd
= NULL
;
641 /*buffers for rpccli_reg_enum_key call*/
642 fstring val_name_buf
;
643 REGVAL_BUFFER val_buf
;
646 uint32
*types_out
= NULL
;
647 REG_VALUE_DATA
**values_out
= NULL
;
648 char **val_names_out
= NULL
;
649 uint32 num_values_out
= 0;
650 uint32 resume_idx
= 0;
655 /*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*/
656 if(NT_STATUS_V(hnd
->status
) == NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED
))
659 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
660 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
664 if(!op
|| !op
->in
.key
|| op
->in
.max_values
== 0 || !mem_ctx
) {
665 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
669 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
671 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
675 /*we need to assume that the max number of values will be enumerated*/
676 types_out
= (uint32
*)talloc_array(mem_ctx
, int, op
->in
.max_values
);
678 hnd
->status
= NT_STATUS_NO_MEMORY
;
682 values_out
= talloc_array(mem_ctx
, REG_VALUE_DATA
*, op
->in
.max_values
);
684 TALLOC_FREE(types_out
);
685 hnd
->status
= NT_STATUS_NO_MEMORY
;
689 val_names_out
= talloc_array(mem_ctx
, char *, op
->in
.max_values
);
691 TALLOC_FREE(types_out
);
692 TALLOC_FREE(values_out
);
693 hnd
->status
= NT_STATUS_NO_MEMORY
;
697 resume_idx
= op
->out
.resume_idx
;
699 ZERO_STRUCT(val_buf
);
701 err
= rpccli_reg_enum_val(pipe_hnd
, mem_ctx
, op
->in
.key
, resume_idx
, val_name_buf
, &types_out
[num_values_out
], &val_buf
);
702 hnd
->status
= werror_to_ntstatus(err
);
704 if(!NT_STATUS_IS_OK(hnd
->status
))
707 values_out
[num_values_out
] = cac_MakeRegValueData(mem_ctx
, types_out
[num_values_out
], val_buf
);
708 val_names_out
[num_values_out
] = talloc_strdup(mem_ctx
, val_name_buf
);
710 if(!val_names_out
[num_values_out
] || !values_out
[num_values_out
]) {
711 hnd
->status
= NT_STATUS_NO_MEMORY
;
717 } while(num_values_out
< op
->in
.max_values
);
719 if(CAC_OP_FAILED(hnd
->status
))
722 op
->out
.types
= types_out
;
723 op
->out
.num_values
= num_values_out
;
724 op
->out
.value_names
= val_names_out
;
725 op
->out
.values
= values_out
;
726 op
->out
.resume_idx
= resume_idx
;
731 int cac_RegSetValue(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegSetValue
*op
) {
732 struct rpc_pipe_client
*pipe_hnd
= NULL
;
735 RPC_DATA_BLOB
*buffer
;
740 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
741 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
745 if(!op
|| !op
->in
.key
|| !op
->in
.val_name
|| !mem_ctx
) {
746 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
750 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
752 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
756 buffer
= cac_MakeRpcDataBlob(mem_ctx
, op
->in
.type
, op
->in
.value
);
760 hnd
->status
= NT_STATUS_NO_MEMORY
;
762 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
767 err
= rpccli_reg_set_val(pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.val_name
, op
->in
.type
, buffer
);
768 hnd
->status
= werror_to_ntstatus(err
);
770 if(!NT_STATUS_IS_OK(hnd
->status
))
774 err
= rpccli_reg_flush_key(pipe_hnd
, mem_ctx
, op
->in
.key
);
775 hnd
->status
= werror_to_ntstatus(err
);
777 if(!NT_STATUS_IS_OK(hnd
->status
))
785 int cac_RegGetVersion(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegGetVersion
*op
) {
786 struct rpc_pipe_client
*pipe_hnd
= NULL
;
794 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
795 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
799 if(!op
|| !op
->in
.key
|| !mem_ctx
) {
800 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
804 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
806 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
810 err
= rpccli_reg_getversion( pipe_hnd
, mem_ctx
, op
->in
.key
, &version_out
);
811 hnd
->status
= werror_to_ntstatus(err
);
813 if(!NT_STATUS_IS_OK(hnd
->status
))
816 op
->out
.version
= version_out
;
821 int cac_RegGetKeySecurity(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegGetKeySecurity
*op
) {
822 struct rpc_pipe_client
*pipe_hnd
= NULL
;
831 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
832 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
836 if(!op
|| !op
->in
.key
|| op
->in
.info_type
== 0 || !mem_ctx
) {
837 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
841 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
843 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
847 err
= rpccli_reg_get_key_sec(pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.info_type
, &buf_size
, &buf
);
848 hnd
->status
= werror_to_ntstatus(err
);
851 if(!NT_STATUS_IS_OK(hnd
->status
)) {
855 op
->out
.size
= buf
.len
;
856 op
->out
.descriptor
= dup_sec_desc(mem_ctx
, buf
.sec
);
858 if (op
->out
.descriptor
== NULL
) {
865 int cac_RegSetKeySecurity(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegSetKeySecurity
*op
) {
866 struct rpc_pipe_client
*pipe_hnd
= NULL
;
872 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
873 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
877 if(!op
|| !op
->in
.key
|| op
->in
.info_type
== 0 || op
->in
.size
== 0 || !op
->in
.descriptor
|| !mem_ctx
) {
878 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
882 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
884 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
888 err
= rpccli_reg_set_key_sec(pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.info_type
, op
->in
.size
, op
->in
.descriptor
);
889 hnd
->status
= werror_to_ntstatus(err
);
892 if(!NT_STATUS_IS_OK(hnd
->status
)) {
899 int cac_RegSaveKey(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegSaveKey
*op
) {
900 struct rpc_pipe_client
*pipe_hnd
= NULL
;
906 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
907 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
911 if(!op
|| !op
->in
.key
|| !op
->in
.filename
|| !mem_ctx
) {
912 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
916 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
918 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
922 err
= rpccli_reg_save_key( pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.filename
);
923 hnd
->status
= werror_to_ntstatus(err
);
926 if(!NT_STATUS_IS_OK(hnd
->status
)) {
933 int cac_Shutdown(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct Shutdown
*op
) {
935 struct rpc_pipe_client
*pipe_hnd
= NULL
;
942 if(!hnd
->_internal
.ctx
) {
943 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
947 if(!op
|| !mem_ctx
) {
948 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
952 srv
= cac_GetServer(hnd
);
954 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
958 /*initialize for winreg pipe if we have to*/
959 if(!hnd
->_internal
.pipes
[PI_SHUTDOWN
]) {
960 if(!(pipe_hnd
= cli_rpc_pipe_open_noauth(&srv
->cli
, PI_SHUTDOWN
, &(hnd
->status
)))) {
964 hnd
->_internal
.pipes
[PI_SHUTDOWN
] = True
;
967 pipe_hnd
= cac_GetPipe(hnd
, PI_SHUTDOWN
);
969 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
973 msg
= (op
->in
.message
!= NULL
) ? op
->in
.message
: talloc_strdup(mem_ctx
, "");
975 hnd
->status
= NT_STATUS_OK
;
977 if(hnd
->_internal
.srv_level
> SRV_WIN_NT4
) {
978 hnd
->status
= rpccli_shutdown_init_ex( pipe_hnd
, mem_ctx
, msg
, op
->in
.timeout
, op
->in
.reboot
, op
->in
.force
, op
->in
.reason
);
981 if(hnd
->_internal
.srv_level
< SRV_WIN_2K
|| !NT_STATUS_IS_OK(hnd
->status
)) {
982 hnd
->status
= rpccli_shutdown_init( pipe_hnd
, mem_ctx
, msg
, op
->in
.timeout
, op
->in
.reboot
, op
->in
.force
);
984 hnd
->_internal
.srv_level
= SRV_WIN_NT4
;
987 if(!NT_STATUS_IS_OK(hnd
->status
)) {
994 int cac_AbortShutdown(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
) {
995 struct rpc_pipe_client
*pipe_hnd
= NULL
;
1000 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_SHUTDOWN
]) {
1001 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1005 pipe_hnd
= cac_GetPipe(hnd
, PI_SHUTDOWN
);
1007 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
1011 hnd
->status
= rpccli_shutdown_abort(pipe_hnd
, mem_ctx
);
1013 if(!NT_STATUS_IS_OK(hnd
->status
))