s3-spoolss: Fixed winreg_printer_openkey to be used in a more generic way.
[Samba/ekacnet.git] / source3 / rpc_server / srv_spoolss_util.c
blob955b95f89d33b1573abb2696d243976582052cd7
1 /*
2 * Unix SMB/CIFS implementation.
4 * SPOOLSS RPC Pipe server / winreg client routines
6 * Copyright (c) 2010 Andreas Schneider <asn@samba.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "srv_spoolss_util.h"
24 #include "../librpc/gen_ndr/srv_winreg.h"
25 #include "../librpc/gen_ndr/cli_winreg.h"
27 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
28 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
29 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
30 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
32 /********************************************************************
33 static helper functions
34 ********************************************************************/
36 /**
37 * @internal
39 * @brief Connect to the interal winreg server and open the given printer key.
41 * The function will create the needed subkeys if they don't exist.
43 * @param[in] mem_ctx The memory context to use.
45 * @param[in] server_info The supplied server info.
47 * @param[out] winreg_pipe A pointer for the winreg rpc client pipe.
49 * @param[in] path The path to the key to open.
51 * @param[in] key The key to open.
53 * @param[in] create_key Set to true if the key should be created if it
54 * doesn't exist.
56 * @param[in] access_mask The access mask to open the key.
58 * @param[out] hive_handle A policy handle for the opened hive.
60 * @param[out] key_handle A policy handle for the opened key.
62 * @return WERR_OK on success, the corresponding DOS error
63 * code if something gone wrong.
65 static WERROR winreg_printer_openkey(TALLOC_CTX *mem_ctx,
66 struct auth_serversupplied_info *server_info,
67 struct rpc_pipe_client **winreg_pipe,
68 const char *path,
69 const char *key,
70 bool create_key,
71 uint32_t access_mask,
72 struct policy_handle *hive_handle,
73 struct policy_handle *key_handle)
75 struct rpc_pipe_client *pipe_handle;
76 struct winreg_String wkey, wkeyclass;
77 char *keyname;
78 NTSTATUS status;
79 WERROR result = WERR_OK;
81 /* create winreg connection */
82 status = rpc_pipe_open_internal(mem_ctx,
83 &ndr_table_winreg.syntax_id,
84 rpc_winreg_dispatch,
85 server_info,
86 &pipe_handle);
87 if (!NT_STATUS_IS_OK(status)) {
88 DEBUG(0, ("winreg_printer_openkey: Could not connect to winreg_pipe: %s\n",
89 nt_errstr(status)));
90 return ntstatus_to_werror(status);
93 status = rpccli_winreg_OpenHKLM(pipe_handle,
94 mem_ctx,
95 NULL,
96 access_mask,
97 hive_handle,
98 &result);
99 if (!NT_STATUS_IS_OK(status)) {
100 DEBUG(0, ("winreg_printer_openkey: Could not open HKLM hive: %s\n",
101 nt_errstr(status)));
102 talloc_free(pipe_handle);
103 if (!W_ERROR_IS_OK(result)) {
104 return result;
106 return ntstatus_to_werror(status);
109 if (key && *key) {
110 keyname = talloc_asprintf(mem_ctx, "%s\\%s", path, key);
111 } else {
112 keyname = talloc_strdup(mem_ctx, path);
114 if (keyname == NULL) {
115 talloc_free(pipe_handle);
116 return WERR_NOMEM;
119 ZERO_STRUCT(wkey);
120 wkey.name = keyname;
122 if (create_key) {
123 enum winreg_CreateAction action = REG_ACTION_NONE;
125 ZERO_STRUCT(wkeyclass);
126 wkeyclass.name = "";
128 status = rpccli_winreg_CreateKey(pipe_handle,
129 mem_ctx,
130 hive_handle,
131 wkey,
132 wkeyclass,
134 access_mask,
135 NULL,
136 key_handle,
137 &action,
138 &result);
139 switch (action) {
140 case REG_ACTION_NONE:
141 DEBUG(8, ("winreg_printer_openkey:createkey did nothing -- huh?\n"));
142 break;
143 case REG_CREATED_NEW_KEY:
144 DEBUG(8, ("winreg_printer_openkey: createkey created %s\n", keyname));
145 break;
146 case REG_OPENED_EXISTING_KEY:
147 DEBUG(8, ("winreg_printer_openkey: createkey opened existing %s\n", keyname));
148 break;
150 } else {
151 status = rpccli_winreg_OpenKey(pipe_handle,
152 mem_ctx,
153 hive_handle,
154 wkey,
156 access_mask,
157 key_handle,
158 &result);
160 if (!NT_STATUS_IS_OK(status)) {
161 talloc_free(pipe_handle);
162 if (!W_ERROR_IS_OK(result)) {
163 return result;
165 return ntstatus_to_werror(status);
168 *winreg_pipe = pipe_handle;
170 return WERR_OK;
174 * @brief Create the registry keyname for the given printer.
176 * @param[in] mem_ctx The memory context to use.
178 * @param[in] printer The name of the printer to get the registry key.
180 * @return The registry key or NULL on error.
182 static char *winreg_printer_data_keyname(TALLOC_CTX *mem_ctx, const char *printer) {
183 return talloc_asprintf(mem_ctx, "%s\\%s", TOP_LEVEL_PRINT_PRINTERS_KEY, printer);
187 * @internal
189 * @brief Enumerate values of an opened key handle and retrieve the data.
191 * @param[in] mem_ctx The memory context to use.
193 * @param[in] pipe_handle The pipe handle for the rpc connection.
195 * @param[in] key_hnd The opened key handle.
197 * @param[out] pnum_values A pointer to store he number of values found.
199 * @param[out] pnum_values A pointer to store the number of values we found.
201 * @return WERR_OK on success, the corresponding DOS error
202 * code if something gone wrong.
204 static WERROR winreg_printer_enumvalues(TALLOC_CTX *mem_ctx,
205 struct rpc_pipe_client *pipe_handle,
206 struct policy_handle *key_hnd,
207 uint32_t *pnum_values,
208 struct spoolss_PrinterEnumValues **penum_values)
210 TALLOC_CTX *tmp_ctx;
211 uint32_t num_subkeys, max_subkeylen, max_classlen;
212 uint32_t num_values, max_valnamelen, max_valbufsize;
213 uint32_t secdescsize;
214 uint32_t i;
215 NTTIME last_changed_time;
216 struct winreg_String classname;
218 struct spoolss_PrinterEnumValues *enum_values;
220 WERROR result = WERR_OK;
221 NTSTATUS status;
223 tmp_ctx = talloc_new(mem_ctx);
224 if (tmp_ctx == NULL) {
225 return WERR_NOMEM;
228 ZERO_STRUCT(classname);
230 status = rpccli_winreg_QueryInfoKey(pipe_handle,
231 tmp_ctx,
232 key_hnd,
233 &classname,
234 &num_subkeys,
235 &max_subkeylen,
236 &max_classlen,
237 &num_values,
238 &max_valnamelen,
239 &max_valbufsize,
240 &secdescsize,
241 &last_changed_time,
242 &result);
243 if (!NT_STATUS_IS_OK(status)) {
244 DEBUG(0, ("winreg_printer_enumvalues: Could not query info: %s\n",
245 nt_errstr(status)));
246 if (!W_ERROR_IS_OK(result)) {
247 goto error;
249 result = ntstatus_to_werror(status);
250 goto error;
253 if (num_values == 0) {
254 *pnum_values = 0;
255 TALLOC_FREE(tmp_ctx);
256 return WERR_OK;
259 enum_values = TALLOC_ARRAY(tmp_ctx, struct spoolss_PrinterEnumValues, num_values);
260 if (enum_values == NULL) {
261 result = WERR_NOMEM;
262 goto error;
265 for (i = 0; i < num_values; i++) {
266 struct spoolss_PrinterEnumValues val;
267 struct winreg_ValNameBuf name_buf;
268 enum winreg_Type type = REG_NONE;
269 uint8_t *data = NULL;
270 uint32_t data_size;
271 uint32_t length;
272 char n = '\0';;
274 name_buf.name = &n;
275 name_buf.size = max_valnamelen + 2;
276 name_buf.length = 0;
278 data_size = max_valbufsize;
279 data = (uint8_t *) TALLOC(tmp_ctx, data_size);
280 length = 0;
282 status = rpccli_winreg_EnumValue(pipe_handle,
283 tmp_ctx,
284 key_hnd,
286 &name_buf,
287 &type,
288 data,
289 &data_size,
290 &length,
291 &result);
292 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
293 result = WERR_OK;
294 status = NT_STATUS_OK;
295 break;
298 if (!NT_STATUS_IS_OK(status)) {
299 DEBUG(0, ("winreg_printer_enumvalues: Could not enumerate values: %s\n",
300 nt_errstr(status)));
301 if (!W_ERROR_IS_OK(result)) {
302 goto error;
304 result = ntstatus_to_werror(status);
305 goto error;
308 if (name_buf.name == NULL) {
309 result = WERR_INVALID_PARAMETER;
310 goto error;
313 val.value_name = talloc_strdup(enum_values, name_buf.name);
314 if (val.value_name == NULL) {
315 result = WERR_NOMEM;
316 goto error;
318 val.value_name_len = strlen_m_term(val.value_name) * 2;
320 val.type = type;
321 val.data_length = data_size;
322 if (val.data_length) {
323 val.data = talloc(enum_values, DATA_BLOB);
324 if (val.data == NULL) {
325 result = WERR_NOMEM;
326 goto error;
328 *val.data = data_blob_talloc(enum_values, data, data_size);
331 enum_values[i] = val;
334 *pnum_values = num_values;
335 if (penum_values) {
336 *penum_values = talloc_move(mem_ctx, &enum_values);
339 result = WERR_OK;
341 error:
342 TALLOC_FREE(tmp_ctx);
343 return result;
347 * @internal
349 * @brief Enumerate subkeys of an opened key handle and get the names.
351 * @param[in] mem_ctx The memory context to use.
353 * @param[in] pipe_handle The pipe handle for the rpc connection.
355 * @param[in] key_hnd The opened key handle.
357 * @param[in] pnum_subkeys A pointer to store the number of found subkeys.
359 * @param[in] psubkeys A pointer to an array to store the found names of
360 * subkeys.
362 * @return WERR_OK on success, the corresponding DOS error
363 * code if something gone wrong.
365 static WERROR winreg_printer_enumkeys(TALLOC_CTX *mem_ctx,
366 struct rpc_pipe_client *pipe_handle,
367 struct policy_handle *key_hnd,
368 uint32_t *pnum_subkeys,
369 const char ***psubkeys)
371 TALLOC_CTX *tmp_ctx;
372 const char **subkeys;
373 uint32_t num_subkeys, max_subkeylen, max_classlen;
374 uint32_t num_values, max_valnamelen, max_valbufsize;
375 uint32_t i;
376 NTTIME last_changed_time;
377 uint32_t secdescsize;
378 struct winreg_String classname;
379 WERROR result = WERR_OK;
380 NTSTATUS status;
382 tmp_ctx = talloc_new(mem_ctx);
383 if (tmp_ctx == NULL) {
384 return WERR_NOMEM;
387 ZERO_STRUCT(classname);
389 status = rpccli_winreg_QueryInfoKey(pipe_handle,
390 tmp_ctx,
391 key_hnd,
392 &classname,
393 &num_subkeys,
394 &max_subkeylen,
395 &max_classlen,
396 &num_values,
397 &max_valnamelen,
398 &max_valbufsize,
399 &secdescsize,
400 &last_changed_time,
401 &result);
402 if (!NT_STATUS_IS_OK(status)) {
403 DEBUG(0, ("winreg_printer_enumkeys: Could not query info: %s\n",
404 nt_errstr(status)));
405 if (!W_ERROR_IS_OK(result)) {
406 goto error;
408 result = ntstatus_to_werror(status);
409 goto error;
412 subkeys = talloc_zero_array(tmp_ctx, const char *, num_subkeys + 2);
413 if (subkeys == NULL) {
414 result = WERR_NOMEM;
415 goto error;
418 if (num_subkeys == 0) {
419 subkeys[0] = talloc_strdup(subkeys, "");
420 if (subkeys[0] == NULL) {
421 result = WERR_NOMEM;
422 goto error;
424 *pnum_subkeys = 0;
425 if (psubkeys) {
426 *psubkeys = talloc_move(mem_ctx, &subkeys);
429 TALLOC_FREE(tmp_ctx);
430 return WERR_OK;
433 for (i = 0; i < num_subkeys; i++) {
434 char c = '\0';
435 char n = '\0';
436 char *name = NULL;
437 struct winreg_StringBuf class_buf;
438 struct winreg_StringBuf name_buf;
439 NTTIME modtime;
441 class_buf.name = &c;
442 class_buf.size = max_classlen + 2;
443 class_buf.length = 0;
445 name_buf.name = &n;
446 name_buf.size = max_subkeylen + 2;
447 name_buf.length = 0;
449 ZERO_STRUCT(modtime);
451 status = rpccli_winreg_EnumKey(pipe_handle,
452 tmp_ctx,
453 key_hnd,
455 &name_buf,
456 &class_buf,
457 &modtime,
458 &result);
459 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
460 result = WERR_OK;
461 status = NT_STATUS_OK;
462 break;
465 if (!NT_STATUS_IS_OK(status)) {
466 DEBUG(0, ("winreg_printer_enumkeys: Could not enumerate keys: %s\n",
467 nt_errstr(status)));
468 if (!W_ERROR_IS_OK(result)) {
469 goto error;
471 result = ntstatus_to_werror(status);
472 goto error;
475 if (name_buf.name == NULL) {
476 result = WERR_INVALID_PARAMETER;
477 goto error;
480 name = talloc_strdup(subkeys, name_buf.name);
481 if (name == NULL) {
482 result = WERR_NOMEM;
483 goto error;
486 subkeys[i] = name;
489 *pnum_subkeys = num_subkeys;
490 if (psubkeys) {
491 *psubkeys = talloc_move(mem_ctx, &subkeys);
494 error:
495 TALLOC_FREE(tmp_ctx);
496 return result;
500 * @internal
502 * @brief A function to delete a key and its subkeys recurively.
504 * @param[in] mem_ctx The memory context to use.
506 * @param[in] pipe_handle The pipe handle for the rpc connection.
508 * @param[in] hive_handle A opened hive handle to the key.
510 * @param[in] access_mask The access mask to access the key.
512 * @param[in] key The key to delete
514 * @return WERR_OK on success, the corresponding DOS error
515 * code if something gone wrong.
517 static WERROR winreg_printer_delete_subkeys(TALLOC_CTX *mem_ctx,
518 struct rpc_pipe_client *pipe_handle,
519 struct policy_handle *hive_handle,
520 uint32_t access_mask,
521 const char *key)
523 const char **subkeys = NULL;
524 uint32_t num_subkeys = 0;
525 struct policy_handle key_hnd;
526 struct winreg_String wkey;
527 WERROR result = WERR_OK;
528 NTSTATUS status;
529 uint32_t i;
531 ZERO_STRUCT(key_hnd);
532 wkey.name = key;
534 DEBUG(2, ("winreg_printer_delete_subkeys: delete key %s\n", key));
535 /* open the key */
536 status = rpccli_winreg_OpenKey(pipe_handle,
537 mem_ctx,
538 hive_handle,
539 wkey,
541 access_mask,
542 &key_hnd,
543 &result);
544 if (!NT_STATUS_IS_OK(status)) {
545 DEBUG(0, ("winreg_printer_delete_subkeys: Could not open key %s: %s\n",
546 wkey.name, nt_errstr(status)));
547 if (!W_ERROR_IS_OK(result)) {
548 return result;
550 return ntstatus_to_werror(status);
553 result = winreg_printer_enumkeys(mem_ctx,
554 pipe_handle,
555 &key_hnd,
556 &num_subkeys,
557 &subkeys);
558 if (!W_ERROR_IS_OK(result)) {
559 goto done;
562 for (i = 0; i < num_subkeys; i++) {
563 /* create key + subkey */
564 char *subkey = talloc_asprintf(mem_ctx, "%s\\%s", key, subkeys[i]);
565 if (subkey == NULL) {
566 goto done;
569 DEBUG(2, ("winreg_printer_delete_subkeys: delete subkey %s\n", subkey));
570 result = winreg_printer_delete_subkeys(mem_ctx,
571 pipe_handle,
572 hive_handle,
573 access_mask,
574 subkey);
575 if (!W_ERROR_IS_OK(result)) {
576 goto done;
580 if (is_valid_policy_hnd(&key_hnd)) {
581 rpccli_winreg_CloseKey(pipe_handle, mem_ctx, &key_hnd, NULL);
584 wkey.name = key;
586 status = rpccli_winreg_DeleteKey(pipe_handle,
587 mem_ctx,
588 hive_handle,
589 wkey,
590 &result);
592 done:
593 if (is_valid_policy_hnd(&key_hnd)) {
594 rpccli_winreg_CloseKey(pipe_handle, mem_ctx, &key_hnd, NULL);
597 return result;
600 /********************************************************************
601 Public winreg function for spoolss
602 ********************************************************************/
604 /* Set printer data over the winreg pipe. */
605 WERROR winreg_set_printer_dataex(struct pipes_struct *p,
606 const char *printer,
607 const char *key,
608 const char *value,
609 enum winreg_Type type,
610 uint8_t *data,
611 uint32_t data_size)
613 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
614 struct rpc_pipe_client *winreg_pipe = NULL;
615 struct policy_handle hive_hnd, key_hnd;
616 struct winreg_String wvalue;
617 char *path;
618 WERROR result = WERR_OK;
619 NTSTATUS status;
620 TALLOC_CTX *tmp_ctx;
622 tmp_ctx = talloc_new(p->mem_ctx);
623 if (tmp_ctx == NULL) {
624 return WERR_NOMEM;
627 path = winreg_printer_data_keyname(tmp_ctx, printer);
628 if (path == NULL) {
629 TALLOC_FREE(tmp_ctx);
630 return WERR_NOMEM;
633 ZERO_STRUCT(hive_hnd);
634 ZERO_STRUCT(key_hnd);
636 DEBUG(8, ("winreg_set_printer_dataex: Open printer key %s, value %s, access_mask: 0x%05x for [%s]\n",
637 key, value, access_mask, printer));
638 result = winreg_printer_openkey(tmp_ctx,
639 p->server_info,
640 &winreg_pipe,
641 path,
642 key,
643 true,
644 access_mask,
645 &hive_hnd,
646 &key_hnd);
647 if (!W_ERROR_IS_OK(result)) {
648 DEBUG(0, ("winreg_set_printer_dataex: Could not open key %s: %s\n",
649 key, win_errstr(result)));
650 goto done;
653 wvalue.name = value;
654 status = rpccli_winreg_SetValue(winreg_pipe,
655 tmp_ctx,
656 &key_hnd,
657 wvalue,
658 type,
659 data,
660 data_size,
661 &result);
662 if (!NT_STATUS_IS_OK(status)) {
663 DEBUG(0, ("winreg_set_printer_dataex: Could not set value %s: %s\n",
664 value, nt_errstr(status)));
665 if (!W_ERROR_IS_OK(result)) {
666 goto done;
668 result = ntstatus_to_werror(status);
669 goto done;
672 result = WERR_OK;
673 done:
674 if (winreg_pipe != NULL) {
675 if (is_valid_policy_hnd(&key_hnd)) {
676 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
678 if (is_valid_policy_hnd(&hive_hnd)) {
679 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
683 TALLOC_FREE(tmp_ctx);
684 return result;
687 /* Get printer data over a winreg pipe. */
688 WERROR winreg_get_printer_dataex(struct pipes_struct *p,
689 const char *printer,
690 const char *key,
691 const char *value,
692 enum winreg_Type *type,
693 uint8_t **data,
694 uint32_t *data_size)
696 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
697 struct rpc_pipe_client *winreg_pipe = NULL;
698 struct policy_handle hive_hnd, key_hnd;
699 struct winreg_String wvalue;
700 enum winreg_Type type_in;
701 char *path;
702 uint8_t *data_in;
703 uint32_t data_in_size = 0;
704 uint32_t value_len = 0;
705 WERROR result = WERR_OK;
706 NTSTATUS status;
707 TALLOC_CTX *tmp_ctx;
709 tmp_ctx = talloc_new(p->mem_ctx);
710 if (tmp_ctx == NULL) {
711 return WERR_NOMEM;
714 path = winreg_printer_data_keyname(tmp_ctx, printer);
715 if (path == NULL) {
716 TALLOC_FREE(tmp_ctx);
717 return WERR_NOMEM;
720 ZERO_STRUCT(hive_hnd);
721 ZERO_STRUCT(key_hnd);
723 result = winreg_printer_openkey(tmp_ctx,
724 p->server_info,
725 &winreg_pipe,
726 path,
727 key,
728 false,
729 access_mask,
730 &hive_hnd,
731 &key_hnd);
732 if (!W_ERROR_IS_OK(result)) {
733 DEBUG(0, ("winreg_get_printer_dataex: Could not open key %s: %s\n",
734 key, win_errstr(result)));
735 goto done;
738 wvalue.name = value;
741 * call QueryValue once with data == NULL to get the
742 * needed memory size to be allocated, then allocate
743 * data buffer and call again.
745 status = rpccli_winreg_QueryValue(winreg_pipe,
746 tmp_ctx,
747 &key_hnd,
748 &wvalue,
749 &type_in,
750 NULL,
751 &data_in_size,
752 &value_len,
753 &result);
754 if (!NT_STATUS_IS_OK(status)) {
755 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
756 value, nt_errstr(status)));
757 if (!W_ERROR_IS_OK(result)) {
758 goto done;
760 result = ntstatus_to_werror(status);
761 goto done;
764 data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
765 if (data_in == NULL) {
766 result = WERR_NOMEM;
767 goto done;
769 value_len = 0;
771 status = rpccli_winreg_QueryValue(winreg_pipe,
772 tmp_ctx,
773 &key_hnd,
774 &wvalue,
775 &type_in,
776 data_in,
777 &data_in_size,
778 &value_len,
779 &result);
780 if (!NT_STATUS_IS_OK(status)) {
781 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
782 value, nt_errstr(status)));
783 if (!W_ERROR_IS_OK(result)) {
784 result = ntstatus_to_werror(status);
786 goto done;
789 *type = type_in;
790 *data_size = data_in_size;
791 if (data_in_size) {
792 *data = talloc_move(p->mem_ctx, &data_in);
795 result = WERR_OK;
796 done:
797 if (winreg_pipe != NULL) {
798 if (is_valid_policy_hnd(&key_hnd)) {
799 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
801 if (is_valid_policy_hnd(&hive_hnd)) {
802 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
806 TALLOC_FREE(tmp_ctx);
807 return result;
810 /* Enumerate on the values of a given key and provide the data. */
811 WERROR winreg_enum_printer_dataex(struct pipes_struct *p,
812 const char *printer,
813 const char *key,
814 uint32_t *pnum_values,
815 struct spoolss_PrinterEnumValues **penum_values)
817 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
818 struct rpc_pipe_client *winreg_pipe = NULL;
819 struct policy_handle hive_hnd, key_hnd;
821 struct spoolss_PrinterEnumValues *enum_values = NULL;
822 uint32_t num_values = 0;
823 char *path;
824 WERROR result = WERR_OK;
826 TALLOC_CTX *tmp_ctx;
828 tmp_ctx = talloc_new(p->mem_ctx);
829 if (tmp_ctx == NULL) {
830 return WERR_NOMEM;
833 path = winreg_printer_data_keyname(tmp_ctx, printer);
834 if (path == NULL) {
835 TALLOC_FREE(tmp_ctx);
836 return WERR_NOMEM;
839 result = winreg_printer_openkey(tmp_ctx,
840 p->server_info,
841 &winreg_pipe,
842 path,
843 key,
844 false,
845 access_mask,
846 &hive_hnd,
847 &key_hnd);
848 if (!W_ERROR_IS_OK(result)) {
849 DEBUG(0, ("winreg_enum_printer_dataex: Could not open key %s: %s\n",
850 key, win_errstr(result)));
851 goto done;
854 result = winreg_printer_enumvalues(tmp_ctx,
855 winreg_pipe,
856 &key_hnd,
857 &num_values,
858 &enum_values);
859 if (!W_ERROR_IS_OK(result)) {
860 DEBUG(0, ("winreg_enum_printer_dataex: Could not enumerate values in %s: %s\n",
861 key, win_errstr(result)));
862 goto done;
865 *pnum_values = num_values;
866 if (penum_values) {
867 *penum_values = talloc_move(p->mem_ctx, &enum_values);
870 result = WERR_OK;
871 done:
872 if (winreg_pipe != NULL) {
873 if (is_valid_policy_hnd(&key_hnd)) {
874 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
876 if (is_valid_policy_hnd(&hive_hnd)) {
877 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
881 TALLOC_FREE(tmp_ctx);
882 return result;
885 /* Delete printer data over a winreg pipe. */
886 WERROR winreg_delete_printer_dataex(struct pipes_struct *p,
887 const char *printer,
888 const char *key,
889 const char *value)
891 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
892 struct rpc_pipe_client *winreg_pipe = NULL;
893 struct policy_handle hive_hnd, key_hnd;
894 struct winreg_String wvalue;
895 char *path;
896 WERROR result = WERR_OK;
897 NTSTATUS status;
899 TALLOC_CTX *tmp_ctx;
901 tmp_ctx = talloc_new(p->mem_ctx);
902 if (tmp_ctx == NULL) {
903 return WERR_NOMEM;
906 path = winreg_printer_data_keyname(tmp_ctx, printer);
907 if (path == NULL) {
908 TALLOC_FREE(tmp_ctx);
909 return WERR_NOMEM;
912 ZERO_STRUCT(hive_hnd);
913 ZERO_STRUCT(key_hnd);
915 result = winreg_printer_openkey(tmp_ctx,
916 p->server_info,
917 &winreg_pipe,
918 path,
919 key,
920 false,
921 access_mask,
922 &hive_hnd,
923 &key_hnd);
924 if (!W_ERROR_IS_OK(result)) {
925 DEBUG(0, ("winreg_delete_printer_dataex: Could not open key %s: %s\n",
926 key, win_errstr(result)));
927 goto done;
930 wvalue.name = value;
931 status = rpccli_winreg_DeleteValue(winreg_pipe,
932 tmp_ctx,
933 &key_hnd,
934 wvalue,
935 &result);
936 if (!NT_STATUS_IS_OK(status)) {
937 DEBUG(0, ("winreg_delete_printer_dataex: Could not delete value %s: %s\n",
938 value, nt_errstr(status)));
939 if (!W_ERROR_IS_OK(result)) {
940 goto done;
942 result = ntstatus_to_werror(status);
943 goto done;
946 result = WERR_OK;
947 done:
948 if (winreg_pipe != NULL) {
949 if (is_valid_policy_hnd(&key_hnd)) {
950 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
952 if (is_valid_policy_hnd(&hive_hnd)) {
953 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
957 TALLOC_FREE(tmp_ctx);
958 return result;
961 /* Enumerate on the subkeys of a given key and provide the data. */
962 WERROR winreg_enum_printer_key(struct pipes_struct *p,
963 const char *printer,
964 const char *key,
965 uint32_t *pnum_subkeys,
966 const char ***psubkeys)
968 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
969 struct rpc_pipe_client *winreg_pipe = NULL;
970 struct policy_handle hive_hnd, key_hnd;
971 char *path;
972 const char **subkeys = NULL;
973 uint32_t num_subkeys = -1;
975 WERROR result = WERR_OK;
977 TALLOC_CTX *tmp_ctx;
979 tmp_ctx = talloc_new(p->mem_ctx);
980 if (tmp_ctx == NULL) {
981 return WERR_NOMEM;
984 path = winreg_printer_data_keyname(tmp_ctx, printer);
985 if (path == NULL) {
986 TALLOC_FREE(tmp_ctx);
987 return WERR_NOMEM;
990 ZERO_STRUCT(hive_hnd);
991 ZERO_STRUCT(key_hnd);
993 result = winreg_printer_openkey(tmp_ctx,
994 p->server_info,
995 &winreg_pipe,
996 path,
997 key,
998 false,
999 access_mask,
1000 &hive_hnd,
1001 &key_hnd);
1002 if (!W_ERROR_IS_OK(result)) {
1003 DEBUG(0, ("winreg_enum_printer_key: Could not open key %s: %s\n",
1004 key, win_errstr(result)));
1005 goto done;
1008 result = winreg_printer_enumkeys(tmp_ctx,
1009 winreg_pipe,
1010 &key_hnd,
1011 &num_subkeys,
1012 &subkeys);
1013 if (!W_ERROR_IS_OK(result)) {
1014 DEBUG(0, ("winreg_enum_printer_key: Could not enumerate subkeys in %s: %s\n",
1015 key, win_errstr(result)));
1016 goto done;
1019 *pnum_subkeys = num_subkeys;
1020 if (psubkeys) {
1021 *psubkeys = talloc_move(p->mem_ctx, &subkeys);
1024 result = WERR_OK;
1025 done:
1026 if (winreg_pipe != NULL) {
1027 if (is_valid_policy_hnd(&key_hnd)) {
1028 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1030 if (is_valid_policy_hnd(&hive_hnd)) {
1031 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1035 TALLOC_FREE(tmp_ctx);
1036 return result;
1039 /* Delete a key with subkeys of a given printer. */
1040 WERROR winreg_delete_printer_key(struct pipes_struct *p,
1041 const char *printer,
1042 const char *key)
1044 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1045 struct rpc_pipe_client *winreg_pipe = NULL;
1046 struct policy_handle hive_hnd, key_hnd;
1047 char *keyname;
1048 char *path;
1049 WERROR result;
1050 TALLOC_CTX *tmp_ctx;
1052 tmp_ctx = talloc_new(p->mem_ctx);
1053 if (tmp_ctx == NULL) {
1054 return WERR_NOMEM;
1057 path = winreg_printer_data_keyname(tmp_ctx, printer);
1058 if (path == NULL) {
1059 TALLOC_FREE(tmp_ctx);
1060 return WERR_NOMEM;
1063 result = winreg_printer_openkey(tmp_ctx,
1064 p->server_info,
1065 &winreg_pipe,
1066 path,
1067 key,
1068 false,
1069 access_mask,
1070 &hive_hnd,
1071 &key_hnd);
1072 if (!W_ERROR_IS_OK(result)) {
1073 /* key doesn't exist */
1074 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1075 result = WERR_OK;
1076 goto done;
1079 DEBUG(0, ("winreg_delete_printer_key: Could not open key %s: %s\n",
1080 key, win_errstr(result)));
1081 goto done;
1084 if (is_valid_policy_hnd(&key_hnd)) {
1085 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1088 keyname = talloc_asprintf(tmp_ctx,
1089 "%s\\%s",
1090 path,
1091 key);
1092 if (keyname == NULL) {
1093 result = WERR_NOMEM;
1094 goto done;
1097 result = winreg_printer_delete_subkeys(tmp_ctx,
1098 winreg_pipe,
1099 &hive_hnd,
1100 access_mask,
1101 keyname);
1102 if (!W_ERROR_IS_OK(result)) {
1103 DEBUG(0, ("winreg_delete_printer_key: Could not delete key %s: %s\n",
1104 key, win_errstr(result)));
1105 goto done;
1108 done:
1109 if (winreg_pipe != NULL) {
1110 if (is_valid_policy_hnd(&key_hnd)) {
1111 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1113 if (is_valid_policy_hnd(&hive_hnd)) {
1114 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1118 TALLOC_FREE(tmp_ctx);
1119 return result;