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 key
= talloc(mem_ctx
, POLICY_HND
);
61 hnd
->status
= NT_STATUS_NO_MEMORY
;
64 err
= rpccli_reg_connect( pipe_hnd
, mem_ctx
, op
->in
.root
, op
->in
.access
, key
);
65 hnd
->status
= werror_to_ntstatus(err
);
67 if(!NT_STATUS_IS_OK(hnd
->status
)) {
76 int cac_RegClose(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, POLICY_HND
*key
) {
77 struct rpc_pipe_client
*pipe_hnd
= NULL
;
83 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
84 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
88 if(!key
|| !mem_ctx
) {
89 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
93 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
95 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
99 err
= rpccli_reg_close(pipe_hnd
, mem_ctx
, key
);
100 hnd
->status
= werror_to_ntstatus(err
);
102 if(!NT_STATUS_IS_OK(hnd
->status
)) {
109 int cac_RegOpenKey(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegOpenKey
*op
) {
110 struct rpc_pipe_client
*pipe_hnd
= NULL
;
114 POLICY_HND
*parent_key
;
116 char *key_name
= NULL
;
119 struct RegConnect rc
;
124 if(!hnd
->_internal
.ctx
) {
125 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
129 if(!op
|| !op
->in
.name
|| !mem_ctx
) {
130 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
135 key_out
= talloc(mem_ctx
, POLICY_HND
);
137 hnd
->status
= NT_STATUS_NO_MEMORY
;
141 if(!op
->in
.parent_key
) {
142 /*then we need to connect to the registry*/
143 if(!cac_ParseRegPath(op
->in
.name
, ®_type
, &key_name
)) {
144 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
148 /*use cac_RegConnect because it handles the session setup*/
151 rc
.in
.access
= op
->in
.access
;
152 rc
.in
.root
= reg_type
;
154 if(!cac_RegConnect(hnd
, mem_ctx
, &rc
)) {
158 /**if they only specified the root key, return the key we just opened*/
159 if(key_name
== NULL
) {
160 op
->out
.key
= rc
.out
.key
;
164 parent_key
= rc
.out
.key
;
167 parent_key
= op
->in
.parent_key
;
168 key_name
= op
->in
.name
;
171 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
173 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
177 err
= rpccli_reg_open_entry( pipe_hnd
, mem_ctx
, parent_key
, key_name
, op
->in
.access
, key_out
);
178 hnd
->status
= werror_to_ntstatus(err
);
180 if(!NT_STATUS_IS_OK(hnd
->status
)) {
184 if(!op
->in
.parent_key
) {
185 /*then close the one that we opened above*/
186 err
= rpccli_reg_close( pipe_hnd
, mem_ctx
, parent_key
);
187 hnd
->status
= werror_to_ntstatus(err
);
189 if(!NT_STATUS_IS_OK(hnd
->status
)) {
194 op
->out
.key
= key_out
;
199 int cac_RegEnumKeys(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegEnumKeys
*op
) {
200 struct rpc_pipe_client
*pipe_hnd
= NULL
;
203 /*buffers for rpccli_reg_enum_key call*/
205 fstring class_name_in
;
208 char **key_names_out
= NULL
;
209 char **class_names_out
= NULL
;
210 time_t *mod_times_out
= NULL
;
211 uint32 num_keys_out
= 0;
212 uint32 resume_idx
= 0;
217 /*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*/
218 if(NT_STATUS_V(hnd
->status
) == NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED
))
221 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
222 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
226 if(!op
|| op
->in
.max_keys
== 0 || !mem_ctx
) {
227 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
231 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
233 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
237 /**the only way to know how many keys to expect is to assume max_keys keys will be found*/
238 key_names_out
= TALLOC_ARRAY(mem_ctx
, char *, op
->in
.max_keys
);
240 hnd
->status
= NT_STATUS_NO_MEMORY
;
244 class_names_out
= TALLOC_ARRAY(mem_ctx
, char *, op
->in
.max_keys
);
245 if(!class_names_out
) {
246 hnd
->status
= NT_STATUS_NO_MEMORY
;
247 talloc_free(key_names_out
);
251 mod_times_out
= TALLOC_ARRAY(mem_ctx
, time_t, op
->in
.max_keys
);
253 hnd
->status
= NT_STATUS_NO_MEMORY
;
254 talloc_free(key_names_out
);
255 talloc_free(class_names_out
);
260 resume_idx
= op
->out
.resume_idx
;
263 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
]);
264 hnd
->status
= werror_to_ntstatus(err
);
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
;
304 struct RegOpenKey rok
;
309 if(!hnd
->_internal
.ctx
) {
310 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
314 if(!op
|| !op
->in
.parent_key
|| !op
->in
.key_name
|| !mem_ctx
) {
315 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
319 /*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized*/
322 rok
.in
.name
= op
->in
.key_name
;
323 rok
.in
.access
= op
->in
.access
;
324 rok
.in
.parent_key
= op
->in
.parent_key
;
326 if(cac_RegOpenKey(hnd
, mem_ctx
, &rok
)) {
327 /*then we got the key, return*/
328 op
->out
.key
= rok
.out
.key
;
332 /*just be ultra-safe*/
333 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
335 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
339 key_out
= talloc(mem_ctx
, POLICY_HND
);
341 hnd
->status
= NT_STATUS_NO_MEMORY
;
345 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
);
346 hnd
->status
= werror_to_ntstatus(err
);
348 if(!NT_STATUS_IS_OK(hnd
->status
)) {
352 op
->out
.key
= key_out
;
358 WERROR
cac_delete_subkeys_recursive(struct rpc_pipe_client
*pipe_hnd
, TALLOC_CTX
*mem_ctx
, POLICY_HND
*key
) {
359 /*NOTE: using cac functions might result in a big(ger) memory bloat, and would probably be far less efficient
360 * so we use the cli_reg functions directly*/
362 WERROR err
= WERR_OK
;
371 while(W_ERROR_IS_OK(err
)) {
372 err
= rpccli_reg_enum_key( pipe_hnd
, mem_ctx
, key
, cur_key
, subkey_name
, class_buf
, &mod_time_buf
);
374 if(!W_ERROR_IS_OK(err
))
377 /*try to open the key with full access*/
378 err
= rpccli_reg_open_entry(pipe_hnd
, mem_ctx
, key
, subkey_name
, REG_KEY_ALL
, &subkey
);
380 if(!W_ERROR_IS_OK(err
))
383 err
= cac_delete_subkeys_recursive(pipe_hnd
, mem_ctx
, &subkey
);
385 if(!W_ERROR_EQUAL(err
,WERR_NO_MORE_ITEMS
) && !W_ERROR_IS_OK(err
))
388 /*flush the key just to be safe*/
389 rpccli_reg_flush_key(pipe_hnd
, mem_ctx
, key
);
391 /*close the key that we opened*/
392 rpccli_reg_close(pipe_hnd
, mem_ctx
, &subkey
);
394 /*now we delete the subkey*/
395 err
= rpccli_reg_delete_key(pipe_hnd
, mem_ctx
, key
, subkey_name
);
407 int cac_RegDeleteKey(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegDeleteKey
*op
) {
408 struct rpc_pipe_client
*pipe_hnd
= NULL
;
414 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
415 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
419 if(!op
|| !op
->in
.parent_key
|| !op
->in
.name
|| !mem_ctx
) {
420 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
424 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
426 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
430 if(op
->in
.recursive
) {
431 /*first open the key, and then delete all of it's subkeys recursively*/
432 struct RegOpenKey rok
;
435 rok
.in
.parent_key
= op
->in
.parent_key
;
436 rok
.in
.name
= op
->in
.name
;
437 rok
.in
.access
= REG_KEY_ALL
;
439 if(!cac_RegOpenKey(hnd
, mem_ctx
, &rok
))
442 err
= cac_delete_subkeys_recursive(pipe_hnd
, mem_ctx
, rok
.out
.key
);
444 /*close the key that we opened*/
445 cac_RegClose(hnd
, mem_ctx
, rok
.out
.key
);
447 hnd
->status
= werror_to_ntstatus(err
);
449 if(NT_STATUS_V(hnd
->status
) != NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED
) && !NT_STATUS_IS_OK(hnd
->status
))
452 /*now go on to actually delete the key*/
455 err
= rpccli_reg_delete_key( pipe_hnd
, mem_ctx
, op
->in
.parent_key
, op
->in
.name
);
456 hnd
->status
= werror_to_ntstatus(err
);
458 if(!NT_STATUS_IS_OK(hnd
->status
)) {
465 int cac_RegDeleteValue(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegDeleteValue
*op
) {
466 struct rpc_pipe_client
*pipe_hnd
= NULL
;
472 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
473 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
477 if(!op
|| !op
->in
.parent_key
|| !op
->in
.name
|| !mem_ctx
) {
478 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
482 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
484 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
488 err
= rpccli_reg_delete_val( pipe_hnd
, mem_ctx
, op
->in
.parent_key
, op
->in
.name
);
489 hnd
->status
= werror_to_ntstatus(err
);
491 if(!NT_STATUS_IS_OK(hnd
->status
)) {
498 int cac_RegQueryKeyInfo(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegQueryKeyInfo
*op
) {
499 struct rpc_pipe_client
*pipe_hnd
= NULL
;
502 char *class_name_out
= NULL
;
503 uint32 class_len
= 0;
504 uint32 num_subkeys_out
= 0;
505 uint32 long_subkey_out
= 0;
506 uint32 long_class_out
= 0;
507 uint32 num_values_out
= 0;
508 uint32 long_value_out
= 0;
509 uint32 long_data_out
= 0;
510 uint32 secdesc_size
= 0;
516 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
517 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
521 if(!op
|| !op
->in
.key
|| !mem_ctx
) {
522 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
526 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
528 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
532 err
= rpccli_reg_query_key( pipe_hnd
, mem_ctx
, op
->in
.key
,
544 hnd
->status
= werror_to_ntstatus(err
);
546 if(!NT_STATUS_IS_OK(hnd
->status
))
549 if(!class_name_out
) {
550 op
->out
.class_name
= talloc_strdup(mem_ctx
, "");
552 else if(class_len
!= 0 && class_name_out
[class_len
- 1] != '\0') {
553 /*then we need to add a '\0'*/
554 op
->out
.class_name
= talloc_size(mem_ctx
, sizeof(char)*(class_len
+ 1));
556 memcpy(op
->out
.class_name
, class_name_out
, class_len
);
558 op
->out
.class_name
[class_len
] = '\0';
560 else { /*then everything worked out fine in the function*/
561 op
->out
.class_name
= talloc_strdup(mem_ctx
, class_name_out
);
564 if(!op
->out
.class_name
) {
565 hnd
->status
= NT_STATUS_NO_MEMORY
;
569 op
->out
.num_subkeys
= num_subkeys_out
;
570 op
->out
.longest_subkey
= long_subkey_out
;
571 op
->out
.longest_class
= long_class_out
;
572 op
->out
.num_values
= num_values_out
;
573 op
->out
.longest_value_name
= long_value_out
;
574 op
->out
.longest_value_data
= long_data_out
;
575 op
->out
.security_desc_size
= secdesc_size
;
576 op
->out
.last_write_time
= nt_time_to_unix(&mod_time
);
581 int cac_RegQueryValue(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegQueryValue
*op
) {
582 struct rpc_pipe_client
*pipe_hnd
= NULL
;
586 REGVAL_BUFFER buffer
;
587 REG_VALUE_DATA
*data_out
= NULL
;
592 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
593 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
597 if(!op
|| !op
->in
.key
|| !op
->in
.val_name
|| !mem_ctx
) {
598 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
602 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
604 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
608 err
= rpccli_reg_query_value(pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.val_name
, &val_type
, &buffer
);
609 hnd
->status
= werror_to_ntstatus(err
);
611 if(!NT_STATUS_IS_OK(hnd
->status
))
614 data_out
= cac_MakeRegValueData(mem_ctx
, val_type
, buffer
);
617 hnd
->status
= NT_STATUS_NO_MEMORY
;
619 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
624 op
->out
.type
= val_type
;
625 op
->out
.data
= data_out
;
631 int cac_RegEnumValues(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegEnumValues
*op
) {
632 struct rpc_pipe_client
*pipe_hnd
= NULL
;
635 /*buffers for rpccli_reg_enum_key call*/
636 fstring val_name_buf
;
637 REGVAL_BUFFER val_buf
;
640 uint32
*types_out
= NULL
;
641 REG_VALUE_DATA
**values_out
= NULL
;
642 char **val_names_out
= NULL
;
643 uint32 num_values_out
= 0;
644 uint32 resume_idx
= 0;
649 /*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*/
650 if(NT_STATUS_V(hnd
->status
) == NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED
))
653 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
654 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
658 if(!op
|| !op
->in
.key
|| op
->in
.max_values
== 0 || !mem_ctx
) {
659 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
663 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
665 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
669 /*we need to assume that the max number of values will be enumerated*/
670 types_out
= (uint32
*)talloc_array(mem_ctx
, int, op
->in
.max_values
);
672 hnd
->status
= NT_STATUS_NO_MEMORY
;
676 values_out
= talloc_array(mem_ctx
, REG_VALUE_DATA
*, op
->in
.max_values
);
678 talloc_free(types_out
);
679 hnd
->status
= NT_STATUS_NO_MEMORY
;
683 val_names_out
= talloc_array(mem_ctx
, char *, op
->in
.max_values
);
685 talloc_free(types_out
);
686 talloc_free(values_out
);
687 hnd
->status
= NT_STATUS_NO_MEMORY
;
691 resume_idx
= op
->out
.resume_idx
;
693 ZERO_STRUCT(val_buf
);
695 err
= rpccli_reg_enum_val(pipe_hnd
, mem_ctx
, op
->in
.key
, resume_idx
, val_name_buf
, &types_out
[num_values_out
], &val_buf
);
696 hnd
->status
= werror_to_ntstatus(err
);
698 if(!NT_STATUS_IS_OK(hnd
->status
))
701 values_out
[num_values_out
] = cac_MakeRegValueData(mem_ctx
, types_out
[num_values_out
], val_buf
);
702 val_names_out
[num_values_out
] = talloc_strdup(mem_ctx
, val_name_buf
);
704 if(!val_names_out
[num_values_out
] || !values_out
[num_values_out
]) {
705 hnd
->status
= NT_STATUS_NO_MEMORY
;
711 } while(num_values_out
< op
->in
.max_values
);
713 if(CAC_OP_FAILED(hnd
->status
))
716 op
->out
.types
= types_out
;
717 op
->out
.num_values
= num_values_out
;
718 op
->out
.value_names
= val_names_out
;
719 op
->out
.values
= values_out
;
720 op
->out
.resume_idx
= resume_idx
;
725 int cac_RegSetValue(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegSetValue
*op
) {
726 struct rpc_pipe_client
*pipe_hnd
= NULL
;
729 RPC_DATA_BLOB
*buffer
;
734 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
735 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
739 if(!op
|| !op
->in
.key
|| !op
->in
.val_name
|| !mem_ctx
) {
740 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
744 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
746 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
750 buffer
= cac_MakeRpcDataBlob(mem_ctx
, op
->in
.type
, op
->in
.value
);
754 hnd
->status
= NT_STATUS_NO_MEMORY
;
756 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
761 err
= rpccli_reg_set_val(pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.val_name
, op
->in
.type
, buffer
);
762 hnd
->status
= werror_to_ntstatus(err
);
764 if(!NT_STATUS_IS_OK(hnd
->status
))
768 err
= rpccli_reg_flush_key(pipe_hnd
, mem_ctx
, op
->in
.key
);
769 hnd
->status
= werror_to_ntstatus(err
);
771 if(!NT_STATUS_IS_OK(hnd
->status
))
779 int cac_RegGetVersion(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegGetVersion
*op
) {
780 struct rpc_pipe_client
*pipe_hnd
= NULL
;
788 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
789 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
793 if(!op
|| !op
->in
.key
|| !mem_ctx
) {
794 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
798 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
800 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
804 err
= rpccli_reg_getversion( pipe_hnd
, mem_ctx
, op
->in
.key
, &version_out
);
805 hnd
->status
= werror_to_ntstatus(err
);
807 if(!NT_STATUS_IS_OK(hnd
->status
))
810 op
->out
.version
= version_out
;
815 int cac_RegGetKeySecurity(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegGetKeySecurity
*op
) {
816 struct rpc_pipe_client
*pipe_hnd
= NULL
;
820 SEC_DESC_BUF
*buf
= NULL
;
825 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
826 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
830 if(!op
|| !op
->in
.key
|| op
->in
.info_type
== 0 || !mem_ctx
) {
831 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
835 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
837 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
841 err
= rpccli_reg_get_key_sec(pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.info_type
, &buf_size
, buf
);
842 hnd
->status
= werror_to_ntstatus(err
);
845 if(!NT_STATUS_IS_OK(hnd
->status
)) {
849 op
->out
.size
= buf
->len
;
850 op
->out
.descriptor
= buf
->sec
;
855 int cac_RegSetKeySecurity(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegSetKeySecurity
*op
) {
856 struct rpc_pipe_client
*pipe_hnd
= NULL
;
862 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
863 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
867 if(!op
|| !op
->in
.key
|| op
->in
.info_type
== 0 || op
->in
.size
== 0 || !op
->in
.descriptor
|| !mem_ctx
) {
868 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
872 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
874 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
878 err
= rpccli_reg_set_key_sec(pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.info_type
, op
->in
.size
, op
->in
.descriptor
);
879 hnd
->status
= werror_to_ntstatus(err
);
882 if(!NT_STATUS_IS_OK(hnd
->status
)) {
889 int cac_RegSaveKey(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct RegSaveKey
*op
) {
890 struct rpc_pipe_client
*pipe_hnd
= NULL
;
896 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_WINREG
]) {
897 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
901 if(!op
|| !op
->in
.key
|| !op
->in
.filename
|| !mem_ctx
) {
902 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
906 pipe_hnd
= cac_GetPipe(hnd
, PI_WINREG
);
908 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
912 err
= rpccli_reg_save_key( pipe_hnd
, mem_ctx
, op
->in
.key
, op
->in
.filename
);
913 hnd
->status
= werror_to_ntstatus(err
);
916 if(!NT_STATUS_IS_OK(hnd
->status
)) {
923 int cac_Shutdown(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
, struct Shutdown
*op
) {
925 struct rpc_pipe_client
*pipe_hnd
= NULL
;
932 if(!hnd
->_internal
.ctx
) {
933 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
937 if(!op
|| !mem_ctx
) {
938 hnd
->status
= NT_STATUS_INVALID_PARAMETER
;
942 srv
= cac_GetServer(hnd
);
944 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
948 /*initialize for winreg pipe if we have to*/
949 if(!hnd
->_internal
.pipes
[PI_SHUTDOWN
]) {
950 if(!(pipe_hnd
= cli_rpc_pipe_open_noauth(&srv
->cli
, PI_SHUTDOWN
, &(hnd
->status
)))) {
954 hnd
->_internal
.pipes
[PI_SHUTDOWN
] = True
;
957 msg
= (op
->in
.message
!= NULL
) ? op
->in
.message
: talloc_strdup(mem_ctx
, "");
959 hnd
->status
= NT_STATUS_OK
;
961 if(hnd
->_internal
.srv_level
> SRV_WIN_NT4
) {
962 hnd
->status
= rpccli_shutdown_init_ex( pipe_hnd
, mem_ctx
, msg
, 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_shutdown_init( pipe_hnd
, mem_ctx
, msg
, op
->in
.timeout
, op
->in
.reboot
, op
->in
.force
);
968 hnd
->_internal
.srv_level
= SRV_WIN_NT4
;
971 if(!NT_STATUS_IS_OK(hnd
->status
)) {
978 int cac_AbortShutdown(CacServerHandle
*hnd
, TALLOC_CTX
*mem_ctx
) {
979 struct rpc_pipe_client
*pipe_hnd
= NULL
;
984 if(!hnd
->_internal
.ctx
|| !hnd
->_internal
.pipes
[PI_SHUTDOWN
]) {
985 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
989 pipe_hnd
= cac_GetPipe(hnd
, PI_SHUTDOWN
);
991 hnd
->status
= NT_STATUS_INVALID_HANDLE
;
995 hnd
->status
= rpccli_shutdown_abort(pipe_hnd
, mem_ctx
);
997 if(!NT_STATUS_IS_OK(hnd
->status
))