r13642: Fix install* scripts to use DESTDIR.
[Samba.git] / source / libmsrpc / cac_winreg.c
blob4c24671a38d22070b2e678854e008f09fe8bce96
1 /*
2 * Unix SMB/CIFS implementation.
3 * MS-RPC client library implementation (WINREG pipe)
4 * Copyright (C) Chris Nicholls 2005.
5 *
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.
21 #include "libmsrpc.h"
22 #include "libmsrpc_internal.h"
25 int cac_RegConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegConnect *op) {
26 SMBCSRV *srv = NULL;
27 struct rpc_pipe_client *pipe_hnd = NULL;
28 POLICY_HND *key = NULL;
29 WERROR err;
31 if(!hnd)
32 return CAC_FAILURE;
34 if(!hnd->_internal.ctx) {
35 hnd->status = NT_STATUS_INVALID_HANDLE;
36 return CAC_FAILURE;
39 if(!op || !op->in.root || !mem_ctx) {
40 hnd->status = NT_STATUS_INVALID_PARAMETER;
41 return CAC_FAILURE;
44 srv = cac_GetServer(hnd);
45 if(!srv) {
46 hnd->status = NT_STATUS_INVALID_CONNECTION;
47 return CAC_FAILURE;
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)))) {
53 return CAC_FAILURE;
56 hnd->_internal.pipes[PI_WINREG] = True;
59 key = talloc(mem_ctx, POLICY_HND);
60 if(!key) {
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)) {
68 return CAC_FAILURE;
71 op->out.key = key;
73 return CAC_SUCCESS;
76 int cac_RegClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *key) {
77 struct rpc_pipe_client *pipe_hnd = NULL;
78 WERROR err;
80 if(!hnd)
81 return CAC_FAILURE;
83 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
84 hnd->status = NT_STATUS_INVALID_HANDLE;
85 return CAC_FAILURE;
88 if(!key || !mem_ctx) {
89 hnd->status = NT_STATUS_INVALID_PARAMETER;
90 return CAC_FAILURE;
93 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
94 if(!pipe_hnd) {
95 hnd->status = NT_STATUS_INVALID_HANDLE;
96 return CAC_FAILURE;
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)) {
103 return CAC_FAILURE;
106 return CAC_SUCCESS;
109 int cac_RegOpenKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegOpenKey *op) {
110 struct rpc_pipe_client *pipe_hnd = NULL;
111 WERROR err;
113 POLICY_HND *key_out;
114 POLICY_HND *parent_key;
116 char *key_name = NULL;
117 uint32 reg_type = 0;
119 struct RegConnect rc;
121 if(!hnd)
122 return CAC_FAILURE;
124 if(!hnd->_internal.ctx) {
125 hnd->status = NT_STATUS_INVALID_HANDLE;
126 return CAC_FAILURE;
129 if(!op || !op->in.name || !mem_ctx) {
130 hnd->status = NT_STATUS_INVALID_PARAMETER;
131 return CAC_FAILURE;
135 key_out = talloc(mem_ctx, POLICY_HND);
136 if(!key_out) {
137 hnd->status = NT_STATUS_NO_MEMORY;
138 return CAC_FAILURE;
141 if(!op->in.parent_key) {
142 /*then we need to connect to the registry*/
143 if(!cac_ParseRegPath(op->in.name, &reg_type, &key_name)) {
144 hnd->status = NT_STATUS_INVALID_PARAMETER;
145 return CAC_FAILURE;
148 /*use cac_RegConnect because it handles the session setup*/
149 ZERO_STRUCT(rc);
151 rc.in.access = op->in.access;
152 rc.in.root = reg_type;
154 if(!cac_RegConnect(hnd, mem_ctx, &rc)) {
155 return CAC_FAILURE;
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;
161 return CAC_SUCCESS;
164 parent_key = rc.out.key;
166 else {
167 parent_key = op->in.parent_key;
168 key_name = op->in.name;
171 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
172 if(!pipe_hnd) {
173 hnd->status = NT_STATUS_INVALID_HANDLE;
174 return CAC_FAILURE;
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)) {
181 return CAC_FAILURE;
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)) {
190 return CAC_FAILURE;
194 op->out.key = key_out;
196 return CAC_SUCCESS;
199 int cac_RegEnumKeys(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegEnumKeys *op) {
200 struct rpc_pipe_client *pipe_hnd = NULL;
201 WERROR err;
203 /*buffers for rpccli_reg_enum_key call*/
204 fstring key_name_in;
205 fstring class_name_in;
207 /*output buffers*/
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;
214 if(!hnd)
215 return CAC_FAILURE;
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))
219 return CAC_FAILURE;
221 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
222 hnd->status = NT_STATUS_INVALID_HANDLE;
223 return CAC_FAILURE;
226 if(!op || op->in.max_keys == 0 || !mem_ctx) {
227 hnd->status = NT_STATUS_INVALID_PARAMETER;
228 return CAC_FAILURE;
231 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
232 if(!pipe_hnd) {
233 hnd->status = NT_STATUS_INVALID_HANDLE;
234 return CAC_FAILURE;
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);
239 if(!key_names_out) {
240 hnd->status = NT_STATUS_NO_MEMORY;
241 return CAC_FAILURE;
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);
248 return CAC_FAILURE;
251 mod_times_out = TALLOC_ARRAY(mem_ctx, time_t, op->in.max_keys);
252 if(!mod_times_out) {
253 hnd->status = NT_STATUS_NO_MEMORY;
254 TALLOC_FREE(key_names_out);
255 TALLOC_FREE(class_names_out);
257 return CAC_FAILURE;
260 resume_idx = op->out.resume_idx;
262 do {
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*/
268 break;
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;
277 break;
280 resume_idx++;
281 num_keys_out++;
282 } while(num_keys_out < op->in.max_keys);
284 if(CAC_OP_FAILED(hnd->status)) {
285 op->out.num_keys = 0;
286 return CAC_FAILURE;
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;
295 return CAC_SUCCESS;
298 int cac_RegCreateKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegCreateKey *op) {
299 struct rpc_pipe_client *pipe_hnd = NULL;
300 WERROR err;
302 POLICY_HND *key_out;
304 struct RegOpenKey rok;
306 if(!hnd)
307 return CAC_FAILURE;
309 if(!hnd->_internal.ctx) {
310 hnd->status = NT_STATUS_INVALID_HANDLE;
311 return CAC_FAILURE;
314 if(!op || !op->in.parent_key || !op->in.key_name || !mem_ctx) {
315 hnd->status = NT_STATUS_INVALID_PARAMETER;
316 return CAC_FAILURE;
319 /*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized*/
320 ZERO_STRUCT(rok);
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;
329 return CAC_SUCCESS;
332 /*just be ultra-safe*/
333 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
334 if(!pipe_hnd) {
335 hnd->status = NT_STATUS_INVALID_HANDLE;
336 return CAC_FAILURE;
339 key_out = talloc(mem_ctx, POLICY_HND);
340 if(!key_out) {
341 hnd->status = NT_STATUS_NO_MEMORY;
342 return CAC_FAILURE;
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)) {
349 return CAC_FAILURE;
352 op->out.key = key_out;
354 return CAC_SUCCESS;
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;
364 POLICY_HND subkey;
365 fstring subkey_name;
366 fstring class_buf;
367 time_t mod_time_buf;
369 int cur_key = 0;
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))
375 break;
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))
381 break;
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))
386 break;
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);
398 cur_key++;
402 return err;
407 int cac_RegDeleteKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteKey *op) {
408 struct rpc_pipe_client *pipe_hnd = NULL;
409 WERROR err;
411 if(!hnd)
412 return CAC_FAILURE;
414 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
415 hnd->status = NT_STATUS_INVALID_HANDLE;
416 return CAC_FAILURE;
419 if(!op || !op->in.parent_key || !op->in.name || !mem_ctx) {
420 hnd->status = NT_STATUS_INVALID_PARAMETER;
421 return CAC_FAILURE;
424 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
425 if(!pipe_hnd) {
426 hnd->status = NT_STATUS_INVALID_HANDLE;
427 return CAC_FAILURE;
430 if(op->in.recursive) {
431 /*first open the key, and then delete all of it's subkeys recursively*/
432 struct RegOpenKey rok;
433 ZERO_STRUCT(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))
440 return CAC_FAILURE;
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))
450 return CAC_FAILURE;
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)) {
459 return CAC_FAILURE;
462 return CAC_SUCCESS;
465 int cac_RegDeleteValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteValue *op) {
466 struct rpc_pipe_client *pipe_hnd = NULL;
467 WERROR err;
469 if(!hnd)
470 return CAC_FAILURE;
472 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
473 hnd->status = NT_STATUS_INVALID_HANDLE;
474 return CAC_FAILURE;
477 if(!op || !op->in.parent_key || !op->in.name || !mem_ctx) {
478 hnd->status = NT_STATUS_INVALID_PARAMETER;
479 return CAC_FAILURE;
482 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
483 if(!pipe_hnd) {
484 hnd->status = NT_STATUS_INVALID_HANDLE;
485 return CAC_FAILURE;
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)) {
492 return CAC_FAILURE;
495 return CAC_SUCCESS;
498 int cac_RegQueryKeyInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegQueryKeyInfo *op) {
499 struct rpc_pipe_client *pipe_hnd = NULL;
500 WERROR err;
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;
511 NTTIME mod_time;
513 if(!hnd)
514 return CAC_FAILURE;
516 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
517 hnd->status = NT_STATUS_INVALID_HANDLE;
518 return CAC_FAILURE;
521 if(!op || !op->in.key || !mem_ctx) {
522 hnd->status = NT_STATUS_INVALID_PARAMETER;
523 return CAC_FAILURE;
526 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
527 if(!pipe_hnd) {
528 hnd->status = NT_STATUS_INVALID_HANDLE;
529 return CAC_FAILURE;
532 err = rpccli_reg_query_key( pipe_hnd, mem_ctx, op->in.key,
533 class_name_out,
534 &class_len,
535 &num_subkeys_out,
536 &long_subkey_out,
537 &long_class_out,
538 &num_values_out,
539 &long_value_out,
540 &long_data_out,
541 &secdesc_size,
542 &mod_time);
544 hnd->status = werror_to_ntstatus(err);
546 if(!NT_STATUS_IS_OK(hnd->status))
547 return CAC_FAILURE;
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;
566 return CAC_FAILURE;
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);
578 return CAC_FAILURE;
581 int cac_RegQueryValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegQueryValue *op) {
582 struct rpc_pipe_client *pipe_hnd = NULL;
583 WERROR err;
585 uint32 val_type;
586 REGVAL_BUFFER buffer;
587 REG_VALUE_DATA *data_out = NULL;
589 if(!hnd)
590 return CAC_FAILURE;
592 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
593 hnd->status = NT_STATUS_INVALID_HANDLE;
594 return CAC_FAILURE;
597 if(!op || !op->in.key || !op->in.val_name || !mem_ctx) {
598 hnd->status = NT_STATUS_INVALID_PARAMETER;
599 return CAC_FAILURE;
602 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
603 if(!pipe_hnd) {
604 hnd->status = NT_STATUS_INVALID_HANDLE;
605 return CAC_FAILURE;
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))
612 return CAC_FAILURE;
614 data_out = cac_MakeRegValueData(mem_ctx, val_type, buffer);
615 if(!data_out) {
616 if(errno == ENOMEM)
617 hnd->status = NT_STATUS_NO_MEMORY;
618 else
619 hnd->status = NT_STATUS_INVALID_PARAMETER;
621 return CAC_FAILURE;
624 op->out.type = val_type;
625 op->out.data = data_out;
627 return CAC_SUCCESS;
631 int cac_RegEnumValues(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegEnumValues *op) {
632 struct rpc_pipe_client *pipe_hnd = NULL;
633 WERROR err;
635 /*buffers for rpccli_reg_enum_key call*/
636 fstring val_name_buf;
637 REGVAL_BUFFER val_buf;
639 /*output buffers*/
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;
646 if(!hnd)
647 return CAC_FAILURE;
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))
651 return CAC_FAILURE;
653 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
654 hnd->status = NT_STATUS_INVALID_HANDLE;
655 return CAC_FAILURE;
658 if(!op || !op->in.key || op->in.max_values == 0 || !mem_ctx) {
659 hnd->status = NT_STATUS_INVALID_PARAMETER;
660 return CAC_FAILURE;
663 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
664 if(!pipe_hnd) {
665 hnd->status = NT_STATUS_INVALID_HANDLE;
666 return CAC_FAILURE;
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);
671 if(!types_out) {
672 hnd->status = NT_STATUS_NO_MEMORY;
673 return CAC_FAILURE;
676 values_out = talloc_array(mem_ctx, REG_VALUE_DATA *, op->in.max_values);
677 if(!values_out) {
678 TALLOC_FREE(types_out);
679 hnd->status = NT_STATUS_NO_MEMORY;
680 return CAC_FAILURE;
683 val_names_out = talloc_array(mem_ctx, char *, op->in.max_values);
684 if(!val_names_out) {
685 TALLOC_FREE(types_out);
686 TALLOC_FREE(values_out);
687 hnd->status = NT_STATUS_NO_MEMORY;
688 return CAC_FAILURE;
691 resume_idx = op->out.resume_idx;
692 do {
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))
699 break;
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;
706 break;
709 num_values_out++;
710 resume_idx++;
711 } while(num_values_out < op->in.max_values);
713 if(CAC_OP_FAILED(hnd->status))
714 return CAC_FAILURE;
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;
722 return CAC_SUCCESS;
725 int cac_RegSetValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSetValue *op) {
726 struct rpc_pipe_client *pipe_hnd = NULL;
727 WERROR err;
729 RPC_DATA_BLOB *buffer;
731 if(!hnd)
732 return CAC_FAILURE;
734 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
735 hnd->status = NT_STATUS_INVALID_HANDLE;
736 return CAC_FAILURE;
739 if(!op || !op->in.key || !op->in.val_name || !mem_ctx) {
740 hnd->status = NT_STATUS_INVALID_PARAMETER;
741 return CAC_FAILURE;
744 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
745 if(!pipe_hnd) {
746 hnd->status = NT_STATUS_INVALID_HANDLE;
747 return CAC_FAILURE;
750 buffer = cac_MakeRpcDataBlob(mem_ctx, op->in.type, op->in.value);
752 if(!buffer) {
753 if(errno == ENOMEM)
754 hnd->status = NT_STATUS_NO_MEMORY;
755 else
756 hnd->status = NT_STATUS_INVALID_PARAMETER;
758 return CAC_FAILURE;
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))
765 return CAC_FAILURE;
767 /*flush*/
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))
772 return CAC_FAILURE;
774 return CAC_SUCCESS;
779 int cac_RegGetVersion(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegGetVersion *op) {
780 struct rpc_pipe_client *pipe_hnd = NULL;
781 WERROR err;
783 uint32 version_out;
785 if(!hnd)
786 return CAC_FAILURE;
788 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
789 hnd->status = NT_STATUS_INVALID_HANDLE;
790 return CAC_FAILURE;
793 if(!op || !op->in.key || !mem_ctx) {
794 hnd->status = NT_STATUS_INVALID_PARAMETER;
795 return CAC_FAILURE;
798 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
799 if(!pipe_hnd) {
800 hnd->status = NT_STATUS_INVALID_HANDLE;
801 return CAC_FAILURE;
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))
808 return CAC_FAILURE;
810 op->out.version = version_out;
812 return CAC_SUCCESS;
815 int cac_RegGetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegGetKeySecurity *op) {
816 struct rpc_pipe_client *pipe_hnd = NULL;
817 WERROR err;
819 uint32 buf_size;
820 SEC_DESC_BUF *buf = NULL;
822 if(!hnd)
823 return CAC_FAILURE;
825 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
826 hnd->status = NT_STATUS_INVALID_HANDLE;
827 return CAC_FAILURE;
830 if(!op || !op->in.key || op->in.info_type == 0 || !mem_ctx) {
831 hnd->status = NT_STATUS_INVALID_PARAMETER;
832 return CAC_FAILURE;
835 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
836 if(!pipe_hnd) {
837 hnd->status = NT_STATUS_INVALID_HANDLE;
838 return CAC_FAILURE;
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)) {
846 return CAC_FAILURE;
849 op->out.size = buf->len;
850 op->out.descriptor = buf->sec;
852 return CAC_SUCCESS;
855 int cac_RegSetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSetKeySecurity *op) {
856 struct rpc_pipe_client *pipe_hnd = NULL;
857 WERROR err;
859 if(!hnd)
860 return CAC_FAILURE;
862 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
863 hnd->status = NT_STATUS_INVALID_HANDLE;
864 return CAC_FAILURE;
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;
869 return CAC_FAILURE;
872 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
873 if(!pipe_hnd) {
874 hnd->status = NT_STATUS_INVALID_HANDLE;
875 return CAC_FAILURE;
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)) {
883 return CAC_FAILURE;
886 return CAC_SUCCESS;
889 int cac_RegSaveKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSaveKey *op) {
890 struct rpc_pipe_client *pipe_hnd = NULL;
891 WERROR err;
893 if(!hnd)
894 return CAC_FAILURE;
896 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
897 hnd->status = NT_STATUS_INVALID_HANDLE;
898 return CAC_FAILURE;
901 if(!op || !op->in.key || !op->in.filename || !mem_ctx) {
902 hnd->status = NT_STATUS_INVALID_PARAMETER;
903 return CAC_FAILURE;
906 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
907 if(!pipe_hnd) {
908 hnd->status = NT_STATUS_INVALID_HANDLE;
909 return CAC_FAILURE;
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)) {
917 return CAC_FAILURE;
920 return CAC_SUCCESS;
923 int cac_Shutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Shutdown *op) {
924 SMBCSRV *srv = NULL;
925 struct rpc_pipe_client *pipe_hnd = NULL;
927 char *msg;
929 if(!hnd)
930 return CAC_FAILURE;
932 if(!hnd->_internal.ctx) {
933 hnd->status = NT_STATUS_INVALID_HANDLE;
934 return CAC_FAILURE;
937 if(!op || !mem_ctx) {
938 hnd->status = NT_STATUS_INVALID_PARAMETER;
939 return CAC_FAILURE;
942 srv = cac_GetServer(hnd);
943 if(!srv) {
944 hnd->status = NT_STATUS_INVALID_HANDLE;
945 return CAC_FAILURE;
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)))) {
951 return CAC_FAILURE;
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)) {
972 return CAC_FAILURE;
975 return CAC_SUCCESS;
978 int cac_AbortShutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx) {
979 struct rpc_pipe_client *pipe_hnd = NULL;
981 if(!hnd)
982 return CAC_FAILURE;
984 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SHUTDOWN]) {
985 hnd->status = NT_STATUS_INVALID_HANDLE;
986 return CAC_FAILURE;
989 pipe_hnd = cac_GetPipe(hnd, PI_SHUTDOWN);
990 if(!pipe_hnd) {
991 hnd->status = NT_STATUS_INVALID_HANDLE;
992 return CAC_FAILURE;
995 hnd->status = rpccli_shutdown_abort(pipe_hnd, mem_ctx);
997 if(!NT_STATUS_IS_OK(hnd->status))
998 return CAC_FAILURE;
1000 return CAC_SUCCESS;