r18919: * Get the new rpccli_winreg_XXXX() functions into the tree
[Samba/bb.git] / source / libmsrpc / cac_winreg.c
blob448197627e5ac96076ccb8294f05d2a2d2f244f3
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;
30 if(!hnd)
31 return CAC_FAILURE;
33 if(!hnd->_internal.ctx) {
34 hnd->status = NT_STATUS_INVALID_HANDLE;
35 return CAC_FAILURE;
38 if(!op || !op->in.root || !mem_ctx) {
39 hnd->status = NT_STATUS_INVALID_PARAMETER;
40 return CAC_FAILURE;
43 srv = cac_GetServer(hnd);
44 if(!srv) {
45 hnd->status = NT_STATUS_INVALID_CONNECTION;
46 return CAC_FAILURE;
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))) {
52 return CAC_FAILURE;
55 hnd->_internal.pipes[PI_WINREG] = True;
58 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
59 if(!pipe_hnd) {
60 hnd->status = NT_STATUS_INVALID_HANDLE;
61 return CAC_FAILURE;
64 key = talloc(mem_ctx, POLICY_HND);
65 if(!key) {
66 hnd->status = NT_STATUS_NO_MEMORY;
67 return CAC_FAILURE;
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)) {
73 return CAC_FAILURE;
76 op->out.key = key;
78 return CAC_SUCCESS;
81 int cac_RegClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *key) {
82 struct rpc_pipe_client *pipe_hnd = NULL;
84 if(!hnd)
85 return CAC_FAILURE;
87 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
88 hnd->status = NT_STATUS_INVALID_HANDLE;
89 return CAC_FAILURE;
92 if(!key || !mem_ctx) {
93 hnd->status = NT_STATUS_INVALID_PARAMETER;
94 return CAC_FAILURE;
97 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
98 if(!pipe_hnd) {
99 hnd->status = NT_STATUS_INVALID_HANDLE;
100 return CAC_FAILURE;
103 hnd->status = rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, key);
105 if(!NT_STATUS_IS_OK(hnd->status)) {
106 return CAC_FAILURE;
109 return CAC_SUCCESS;
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;
116 POLICY_HND *key_out;
117 POLICY_HND *parent_key;
119 char *key_name = NULL;
120 uint32 reg_type = 0;
122 struct RegConnect rc;
124 if(!hnd)
125 return CAC_FAILURE;
127 if(!hnd->_internal.ctx) {
128 hnd->status = NT_STATUS_INVALID_HANDLE;
129 return CAC_FAILURE;
132 if(!op || !op->in.name || !mem_ctx) {
133 hnd->status = NT_STATUS_INVALID_PARAMETER;
134 return CAC_FAILURE;
138 key_out = talloc(mem_ctx, POLICY_HND);
139 if(!key_out) {
140 hnd->status = NT_STATUS_NO_MEMORY;
141 return CAC_FAILURE;
144 if(!op->in.parent_key) {
145 /*then we need to connect to the registry*/
146 if(!cac_ParseRegPath(op->in.name, &reg_type, &key_name)) {
147 hnd->status = NT_STATUS_INVALID_PARAMETER;
148 return CAC_FAILURE;
151 /*use cac_RegConnect because it handles the session setup*/
152 ZERO_STRUCT(rc);
154 rc.in.access = op->in.access;
155 rc.in.root = reg_type;
157 if(!cac_RegConnect(hnd, mem_ctx, &rc)) {
158 return CAC_FAILURE;
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;
164 return CAC_SUCCESS;
167 parent_key = rc.out.key;
169 else {
170 parent_key = op->in.parent_key;
171 key_name = op->in.name;
174 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
175 if(!pipe_hnd) {
176 hnd->status = NT_STATUS_INVALID_HANDLE;
177 return CAC_FAILURE;
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)) {
184 return CAC_FAILURE;
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)) {
192 return CAC_FAILURE;
196 op->out.key = key_out;
198 return CAC_SUCCESS;
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*/
205 fstring key_name_in;
206 fstring class_name_in;
208 /*output buffers*/
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;
215 if(!hnd)
216 return CAC_FAILURE;
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))
220 return CAC_FAILURE;
222 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
223 hnd->status = NT_STATUS_INVALID_HANDLE;
224 return CAC_FAILURE;
227 if(!op || op->in.max_keys == 0 || !mem_ctx) {
228 hnd->status = NT_STATUS_INVALID_PARAMETER;
229 return CAC_FAILURE;
232 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
233 if(!pipe_hnd) {
234 hnd->status = NT_STATUS_INVALID_HANDLE;
235 return CAC_FAILURE;
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);
240 if(!key_names_out) {
241 hnd->status = NT_STATUS_NO_MEMORY;
242 return CAC_FAILURE;
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);
249 return CAC_FAILURE;
252 mod_times_out = TALLOC_ARRAY(mem_ctx, time_t, op->in.max_keys);
253 if(!mod_times_out) {
254 hnd->status = NT_STATUS_NO_MEMORY;
255 TALLOC_FREE(key_names_out);
256 TALLOC_FREE(class_names_out);
258 return CAC_FAILURE;
261 resume_idx = op->out.resume_idx;
263 do {
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*/
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 POLICY_HND *key_out;
301 struct RegOpenKey rok;
302 struct winreg_String key_string, class_string;
303 enum winreg_CreateAction action = 0;
305 if(!hnd)
306 return CAC_FAILURE;
308 if(!hnd->_internal.ctx) {
309 hnd->status = NT_STATUS_INVALID_HANDLE;
310 return CAC_FAILURE;
313 if(!op || !op->in.parent_key || !op->in.key_name || !mem_ctx) {
314 hnd->status = NT_STATUS_INVALID_PARAMETER;
315 return CAC_FAILURE;
318 /*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized*/
319 ZERO_STRUCT(rok);
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;
328 return CAC_SUCCESS;
331 /*just be ultra-safe*/
332 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
333 if(!pipe_hnd) {
334 hnd->status = NT_STATUS_INVALID_HANDLE;
335 return CAC_FAILURE;
338 key_out = talloc(mem_ctx, POLICY_HND);
339 if(!key_out) {
340 hnd->status = NT_STATUS_NO_MEMORY;
341 return CAC_FAILURE;
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)) {
350 return CAC_FAILURE;
353 op->out.key = key_out;
355 return CAC_SUCCESS;
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;
365 POLICY_HND subkey;
366 fstring subkey_name;
367 fstring class_buf;
368 time_t mod_time_buf;
370 int cur_key = 0;
372 while(W_ERROR_IS_OK(err)) {
373 struct winreg_String key_string;
374 NTSTATUS status;
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) )
379 break;
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) )
386 break;
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))
391 break;
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);
405 cur_key++;
409 return err;
414 int cac_RegDeleteKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteKey *op) {
415 struct rpc_pipe_client *pipe_hnd = NULL;
416 WERROR err;
417 struct winreg_String key_string;
419 if(!hnd)
420 return CAC_FAILURE;
422 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
423 hnd->status = NT_STATUS_INVALID_HANDLE;
424 return CAC_FAILURE;
427 if(!op || !op->in.parent_key || !op->in.name || !mem_ctx) {
428 hnd->status = NT_STATUS_INVALID_PARAMETER;
429 return CAC_FAILURE;
432 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
433 if(!pipe_hnd) {
434 hnd->status = NT_STATUS_INVALID_HANDLE;
435 return CAC_FAILURE;
438 if(op->in.recursive) {
439 /*first open the key, and then delete all of it's subkeys recursively*/
440 struct RegOpenKey rok;
441 ZERO_STRUCT(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))
448 return CAC_FAILURE;
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))
458 return CAC_FAILURE;
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)) {
467 return CAC_FAILURE;
470 return CAC_SUCCESS;
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;
477 if(!hnd)
478 return CAC_FAILURE;
480 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
481 hnd->status = NT_STATUS_INVALID_HANDLE;
482 return CAC_FAILURE;
485 if(!op || !op->in.parent_key || !op->in.name || !mem_ctx) {
486 hnd->status = NT_STATUS_INVALID_PARAMETER;
487 return CAC_FAILURE;
490 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
491 if(!pipe_hnd) {
492 hnd->status = NT_STATUS_INVALID_HANDLE;
493 return CAC_FAILURE;
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)) {
500 return CAC_FAILURE;
503 return CAC_SUCCESS;
506 #if 0
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;
513 WERROR err;
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;
524 NTTIME mod_time;
526 if(!hnd)
527 return CAC_FAILURE;
529 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
530 hnd->status = NT_STATUS_INVALID_HANDLE;
531 return CAC_FAILURE;
534 if(!op || !op->in.key || !mem_ctx) {
535 hnd->status = NT_STATUS_INVALID_PARAMETER;
536 return CAC_FAILURE;
539 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
540 if(!pipe_hnd) {
541 hnd->status = NT_STATUS_INVALID_HANDLE;
542 return CAC_FAILURE;
545 err = rpccli_reg_query_key( pipe_hnd, mem_ctx, op->in.key,
546 class_name_out,
547 &class_len,
548 &num_subkeys_out,
549 &long_subkey_out,
550 &long_class_out,
551 &num_values_out,
552 &long_value_out,
553 &long_data_out,
554 &secdesc_size,
555 &mod_time);
557 hnd->status = werror_to_ntstatus(err);
559 if(!NT_STATUS_IS_OK(hnd->status))
560 return CAC_FAILURE;
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;
579 return CAC_FAILURE;
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);
591 return CAC_FAILURE;
593 #endif
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;
601 uint8 *buf;
602 uint32 buf_size = 4096;
603 uint32 length = 0;
605 if(!hnd)
606 return CAC_FAILURE;
608 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
609 hnd->status = NT_STATUS_INVALID_HANDLE;
610 return CAC_FAILURE;
613 if(!op || !op->in.key || !op->in.val_name || !mem_ctx) {
614 hnd->status = NT_STATUS_INVALID_PARAMETER;
615 return CAC_FAILURE;
618 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
619 if(!pipe_hnd) {
620 hnd->status = NT_STATUS_INVALID_HANDLE;
621 return CAC_FAILURE;
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;
628 return CAC_FAILURE;
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))
635 return CAC_FAILURE;
637 init_regval_buffer( &buffer, buf, length );
639 data_out = cac_MakeRegValueData(mem_ctx, val_type, buffer);
640 if(!data_out) {
641 if(errno == ENOMEM)
642 hnd->status = NT_STATUS_NO_MEMORY;
643 else
644 hnd->status = NT_STATUS_INVALID_PARAMETER;
646 return CAC_FAILURE;
649 op->out.type = val_type;
650 op->out.data = data_out;
652 return CAC_SUCCESS;
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;
663 /*output buffers*/
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;
670 if(!hnd)
671 return CAC_FAILURE;
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))
675 return CAC_FAILURE;
677 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
678 hnd->status = NT_STATUS_INVALID_HANDLE;
679 return CAC_FAILURE;
682 if(!op || !op->in.key || op->in.max_values == 0 || !mem_ctx) {
683 hnd->status = NT_STATUS_INVALID_PARAMETER;
684 return CAC_FAILURE;
687 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
688 if(!pipe_hnd) {
689 hnd->status = NT_STATUS_INVALID_HANDLE;
690 return CAC_FAILURE;
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);
695 if(!types_out) {
696 hnd->status = NT_STATUS_NO_MEMORY;
697 return CAC_FAILURE;
700 values_out = talloc_array(mem_ctx, REG_VALUE_DATA *, op->in.max_values);
701 if(!values_out) {
702 TALLOC_FREE(types_out);
703 hnd->status = NT_STATUS_NO_MEMORY;
704 return CAC_FAILURE;
707 val_names_out = talloc_array(mem_ctx, char *, op->in.max_values);
708 if(!val_names_out) {
709 TALLOC_FREE(types_out);
710 TALLOC_FREE(values_out);
711 hnd->status = NT_STATUS_NO_MEMORY;
712 return CAC_FAILURE;
715 resume_idx = op->out.resume_idx;
716 do {
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))
722 break;
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;
729 break;
732 num_values_out++;
733 resume_idx++;
734 } while(num_values_out < op->in.max_values);
736 if(CAC_OP_FAILED(hnd->status))
737 return CAC_FAILURE;
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;
745 return CAC_SUCCESS;
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;
754 if(!hnd)
755 return CAC_FAILURE;
757 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
758 hnd->status = NT_STATUS_INVALID_HANDLE;
759 return CAC_FAILURE;
762 if(!op || !op->in.key || !op->in.val_name || !mem_ctx) {
763 hnd->status = NT_STATUS_INVALID_PARAMETER;
764 return CAC_FAILURE;
767 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
768 if(!pipe_hnd) {
769 hnd->status = NT_STATUS_INVALID_HANDLE;
770 return CAC_FAILURE;
773 buffer = cac_MakeRpcDataBlob(mem_ctx, op->in.type, op->in.value);
775 if(!buffer) {
776 if(errno == ENOMEM)
777 hnd->status = NT_STATUS_NO_MEMORY;
778 else
779 hnd->status = NT_STATUS_INVALID_PARAMETER;
781 return CAC_FAILURE;
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))
788 return CAC_FAILURE;
790 /*flush*/
791 hnd->status = rpccli_winreg_FlushKey(pipe_hnd, mem_ctx, op->in.key);
793 if(!NT_STATUS_IS_OK(hnd->status))
794 return CAC_FAILURE;
796 return CAC_SUCCESS;
801 int cac_RegGetVersion(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegGetVersion *op) {
802 struct rpc_pipe_client *pipe_hnd = NULL;
803 uint32 version_out;
805 if(!hnd)
806 return CAC_FAILURE;
808 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
809 hnd->status = NT_STATUS_INVALID_HANDLE;
810 return CAC_FAILURE;
813 if(!op || !op->in.key || !mem_ctx) {
814 hnd->status = NT_STATUS_INVALID_PARAMETER;
815 return CAC_FAILURE;
818 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
819 if(!pipe_hnd) {
820 hnd->status = NT_STATUS_INVALID_HANDLE;
821 return CAC_FAILURE;
824 hnd->status = rpccli_winreg_GetVersion( pipe_hnd, mem_ctx, op->in.key, &version_out);
826 if(!NT_STATUS_IS_OK(hnd->status))
827 return CAC_FAILURE;
829 op->out.version = version_out;
831 return CAC_SUCCESS;
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;
838 ZERO_STRUCT(keysec);
840 if(!hnd)
841 return CAC_FAILURE;
843 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
844 hnd->status = NT_STATUS_INVALID_HANDLE;
845 return CAC_FAILURE;
848 if(!op || !op->in.key || op->in.info_type == 0 || !mem_ctx) {
849 hnd->status = NT_STATUS_INVALID_PARAMETER;
850 return CAC_FAILURE;
853 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
854 if(!pipe_hnd) {
855 hnd->status = NT_STATUS_INVALID_HANDLE;
856 return CAC_FAILURE;
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)) {
862 return CAC_FAILURE;
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);
868 #endif
870 if (op->out.descriptor == NULL) {
871 return CAC_FAILURE;
874 return CAC_SUCCESS;
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 );
883 if(!hnd)
884 return CAC_FAILURE;
886 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
887 hnd->status = NT_STATUS_INVALID_HANDLE;
888 return CAC_FAILURE;
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;
893 return CAC_FAILURE;
896 pipe_hnd = cac_GetPipe(hnd, PI_WINREG);
897 if(!pipe_hnd) {
898 hnd->status = NT_STATUS_INVALID_HANDLE;
899 return CAC_FAILURE;
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)) {
906 return CAC_FAILURE;
909 return CAC_SUCCESS;
912 int cac_Shutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Shutdown *op) {
913 SMBCSRV *srv = NULL;
914 struct rpc_pipe_client *pipe_hnd = NULL;
915 struct initshutdown_String msg_string;
916 struct initshutdown_String_sub s;
918 char *msg;
920 if(!hnd)
921 return CAC_FAILURE;
923 if(!hnd->_internal.ctx) {
924 hnd->status = NT_STATUS_INVALID_HANDLE;
925 return CAC_FAILURE;
928 if(!op || !mem_ctx) {
929 hnd->status = NT_STATUS_INVALID_PARAMETER;
930 return CAC_FAILURE;
933 srv = cac_GetServer(hnd);
934 if(!srv) {
935 hnd->status = NT_STATUS_INVALID_HANDLE;
936 return CAC_FAILURE;
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)))) {
942 return CAC_FAILURE;
945 hnd->_internal.pipes[PI_INITSHUTDOWN] = True;
948 pipe_hnd = cac_GetPipe(hnd, PI_INITSHUTDOWN);
949 if(!pipe_hnd) {
950 hnd->status = NT_STATUS_INVALID_HANDLE;
951 return CAC_FAILURE;
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)) {
973 return CAC_FAILURE;
976 return CAC_SUCCESS;
979 int cac_AbortShutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx) {
980 struct rpc_pipe_client *pipe_hnd = NULL;
982 if(!hnd)
983 return CAC_FAILURE;
985 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_INITSHUTDOWN]) {
986 hnd->status = NT_STATUS_INVALID_HANDLE;
987 return CAC_FAILURE;
990 pipe_hnd = cac_GetPipe(hnd, PI_INITSHUTDOWN);
991 if(!pipe_hnd) {
992 hnd->status = NT_STATUS_INVALID_HANDLE;
993 return CAC_FAILURE;
996 hnd->status = rpccli_initshutdown_Abort(pipe_hnd, mem_ctx, NULL);
998 if(!NT_STATUS_IS_OK(hnd->status))
999 return CAC_FAILURE;
1001 return CAC_SUCCESS;