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/>.
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 ********************************************************************/
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
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,
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;
79 WERROR result = WERR_OK;
81 /* create winreg connection */
82 status = rpc_pipe_open_internal(mem_ctx,
83 &ndr_table_winreg.syntax_id,
87 if (!NT_STATUS_IS_OK(status)) {
88 DEBUG(0, ("winreg_printer_openkey: Could not connect to winreg_pipe: %s\n",
90 return ntstatus_to_werror(status);
93 status = rpccli_winreg_OpenHKLM(pipe_handle,
99 if (!NT_STATUS_IS_OK(status)) {
100 DEBUG(0, ("winreg_printer_openkey: Could not open HKLM hive: %s\n",
102 talloc_free(pipe_handle);
103 if (!W_ERROR_IS_OK(result)) {
106 return ntstatus_to_werror(status);
110 keyname = talloc_asprintf(mem_ctx, "%s\\%s", path, key);
112 keyname = talloc_strdup(mem_ctx, path);
114 if (keyname == NULL) {
115 talloc_free(pipe_handle);
123 enum winreg_CreateAction action = REG_ACTION_NONE;
125 ZERO_STRUCT(wkeyclass);
128 status = rpccli_winreg_CreateKey(pipe_handle,
140 case REG_ACTION_NONE:
141 DEBUG(8, ("winreg_printer_openkey:createkey did nothing -- huh?\n"));
143 case REG_CREATED_NEW_KEY:
144 DEBUG(8, ("winreg_printer_openkey: createkey created %s\n", keyname));
146 case REG_OPENED_EXISTING_KEY:
147 DEBUG(8, ("winreg_printer_openkey: createkey opened existing %s\n", keyname));
151 status = rpccli_winreg_OpenKey(pipe_handle,
160 if (!NT_STATUS_IS_OK(status)) {
161 talloc_free(pipe_handle);
162 if (!W_ERROR_IS_OK(result)) {
165 return ntstatus_to_werror(status);
168 *winreg_pipe = pipe_handle;
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);
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)
211 uint32_t num_subkeys, max_subkeylen, max_classlen;
212 uint32_t num_values, max_valnamelen, max_valbufsize;
213 uint32_t secdescsize;
215 NTTIME last_changed_time;
216 struct winreg_String classname;
218 struct spoolss_PrinterEnumValues *enum_values;
220 WERROR result = WERR_OK;
223 tmp_ctx = talloc_new(mem_ctx);
224 if (tmp_ctx == NULL) {
228 ZERO_STRUCT(classname);
230 status = rpccli_winreg_QueryInfoKey(pipe_handle,
243 if (!NT_STATUS_IS_OK(status)) {
244 DEBUG(0, ("winreg_printer_enumvalues: Could not query info: %s\n",
246 if (!W_ERROR_IS_OK(result)) {
249 result = ntstatus_to_werror(status);
253 if (num_values == 0) {
255 TALLOC_FREE(tmp_ctx);
259 enum_values = TALLOC_ARRAY(tmp_ctx, struct spoolss_PrinterEnumValues, num_values);
260 if (enum_values == NULL) {
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;
275 name_buf.size = max_valnamelen + 2;
278 data_size = max_valbufsize;
279 data = (uint8_t *) TALLOC(tmp_ctx, data_size);
282 status = rpccli_winreg_EnumValue(pipe_handle,
292 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
294 status = NT_STATUS_OK;
298 if (!NT_STATUS_IS_OK(status)) {
299 DEBUG(0, ("winreg_printer_enumvalues: Could not enumerate values: %s\n",
301 if (!W_ERROR_IS_OK(result)) {
304 result = ntstatus_to_werror(status);
308 if (name_buf.name == NULL) {
309 result = WERR_INVALID_PARAMETER;
313 val.value_name = talloc_strdup(enum_values, name_buf.name);
314 if (val.value_name == NULL) {
318 val.value_name_len = strlen_m_term(val.value_name) * 2;
321 val.data_length = data_size;
322 if (val.data_length) {
323 val.data = talloc(enum_values, DATA_BLOB);
324 if (val.data == NULL) {
328 *val.data = data_blob_talloc(enum_values, data, data_size);
331 enum_values[i] = val;
334 *pnum_values = num_values;
336 *penum_values = talloc_move(mem_ctx, &enum_values);
342 TALLOC_FREE(tmp_ctx);
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
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)
372 const char **subkeys;
373 uint32_t num_subkeys, max_subkeylen, max_classlen;
374 uint32_t num_values, max_valnamelen, max_valbufsize;
376 NTTIME last_changed_time;
377 uint32_t secdescsize;
378 struct winreg_String classname;
379 WERROR result = WERR_OK;
382 tmp_ctx = talloc_new(mem_ctx);
383 if (tmp_ctx == NULL) {
387 ZERO_STRUCT(classname);
389 status = rpccli_winreg_QueryInfoKey(pipe_handle,
402 if (!NT_STATUS_IS_OK(status)) {
403 DEBUG(0, ("winreg_printer_enumkeys: Could not query info: %s\n",
405 if (!W_ERROR_IS_OK(result)) {
408 result = ntstatus_to_werror(status);
412 subkeys = talloc_zero_array(tmp_ctx, const char *, num_subkeys + 2);
413 if (subkeys == NULL) {
418 if (num_subkeys == 0) {
419 subkeys[0] = talloc_strdup(subkeys, "");
420 if (subkeys[0] == NULL) {
426 *psubkeys = talloc_move(mem_ctx, &subkeys);
429 TALLOC_FREE(tmp_ctx);
433 for (i = 0; i < num_subkeys; i++) {
437 struct winreg_StringBuf class_buf;
438 struct winreg_StringBuf name_buf;
442 class_buf.size = max_classlen + 2;
443 class_buf.length = 0;
446 name_buf.size = max_subkeylen + 2;
449 ZERO_STRUCT(modtime);
451 status = rpccli_winreg_EnumKey(pipe_handle,
459 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
461 status = NT_STATUS_OK;
465 if (!NT_STATUS_IS_OK(status)) {
466 DEBUG(0, ("winreg_printer_enumkeys: Could not enumerate keys: %s\n",
468 if (!W_ERROR_IS_OK(result)) {
471 result = ntstatus_to_werror(status);
475 if (name_buf.name == NULL) {
476 result = WERR_INVALID_PARAMETER;
480 name = talloc_strdup(subkeys, name_buf.name);
489 *pnum_subkeys = num_subkeys;
491 *psubkeys = talloc_move(mem_ctx, &subkeys);
495 TALLOC_FREE(tmp_ctx);
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,
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;
531 ZERO_STRUCT(key_hnd);
534 DEBUG(2, ("winreg_printer_delete_subkeys: delete key %s\n", key));
536 status = rpccli_winreg_OpenKey(pipe_handle,
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)) {
550 return ntstatus_to_werror(status);
553 result = winreg_printer_enumkeys(mem_ctx,
558 if (!W_ERROR_IS_OK(result)) {
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) {
569 DEBUG(2, ("winreg_printer_delete_subkeys: delete subkey %s\n", subkey));
570 result = winreg_printer_delete_subkeys(mem_ctx,
575 if (!W_ERROR_IS_OK(result)) {
580 if (is_valid_policy_hnd(&key_hnd)) {
581 rpccli_winreg_CloseKey(pipe_handle, mem_ctx, &key_hnd, NULL);
586 status = rpccli_winreg_DeleteKey(pipe_handle,
593 if (is_valid_policy_hnd(&key_hnd)) {
594 rpccli_winreg_CloseKey(pipe_handle, mem_ctx, &key_hnd, NULL);
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,
609 enum winreg_Type type,
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;
618 WERROR result = WERR_OK;
622 tmp_ctx = talloc_new(p->mem_ctx);
623 if (tmp_ctx == NULL) {
627 path = winreg_printer_data_keyname(tmp_ctx, printer);
629 TALLOC_FREE(tmp_ctx);
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,
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)));
654 status = rpccli_winreg_SetValue(winreg_pipe,
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)) {
668 result = ntstatus_to_werror(status);
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);
687 /* Get printer data over a winreg pipe. */
688 WERROR winreg_get_printer_dataex(struct pipes_struct *p,
692 enum winreg_Type *type,
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;
703 uint32_t data_in_size = 0;
704 uint32_t value_len = 0;
705 WERROR result = WERR_OK;
709 tmp_ctx = talloc_new(p->mem_ctx);
710 if (tmp_ctx == NULL) {
714 path = winreg_printer_data_keyname(tmp_ctx, printer);
716 TALLOC_FREE(tmp_ctx);
720 ZERO_STRUCT(hive_hnd);
721 ZERO_STRUCT(key_hnd);
723 result = winreg_printer_openkey(tmp_ctx,
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)));
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,
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)) {
760 result = ntstatus_to_werror(status);
764 data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
765 if (data_in == NULL) {
771 status = rpccli_winreg_QueryValue(winreg_pipe,
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);
790 *data_size = data_in_size;
792 *data = talloc_move(p->mem_ctx, &data_in);
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);
810 /* Enumerate on the values of a given key and provide the data. */
811 WERROR winreg_enum_printer_dataex(struct pipes_struct *p,
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;
824 WERROR result = WERR_OK;
828 tmp_ctx = talloc_new(p->mem_ctx);
829 if (tmp_ctx == NULL) {
833 path = winreg_printer_data_keyname(tmp_ctx, printer);
835 TALLOC_FREE(tmp_ctx);
839 result = winreg_printer_openkey(tmp_ctx,
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)));
854 result = winreg_printer_enumvalues(tmp_ctx,
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)));
865 *pnum_values = num_values;
867 *penum_values = talloc_move(p->mem_ctx, &enum_values);
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);
885 /* Delete printer data over a winreg pipe. */
886 WERROR winreg_delete_printer_dataex(struct pipes_struct *p,
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;
896 WERROR result = WERR_OK;
901 tmp_ctx = talloc_new(p->mem_ctx);
902 if (tmp_ctx == NULL) {
906 path = winreg_printer_data_keyname(tmp_ctx, printer);
908 TALLOC_FREE(tmp_ctx);
912 ZERO_STRUCT(hive_hnd);
913 ZERO_STRUCT(key_hnd);
915 result = winreg_printer_openkey(tmp_ctx,
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)));
931 status = rpccli_winreg_DeleteValue(winreg_pipe,
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)) {
942 result = ntstatus_to_werror(status);
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);
961 /* Enumerate on the subkeys of a given key and provide the data. */
962 WERROR winreg_enum_printer_key(struct pipes_struct *p,
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;
972 const char **subkeys = NULL;
973 uint32_t num_subkeys = -1;
975 WERROR result = WERR_OK;
979 tmp_ctx = talloc_new(p->mem_ctx);
980 if (tmp_ctx == NULL) {
984 path = winreg_printer_data_keyname(tmp_ctx, printer);
986 TALLOC_FREE(tmp_ctx);
990 ZERO_STRUCT(hive_hnd);
991 ZERO_STRUCT(key_hnd);
993 result = winreg_printer_openkey(tmp_ctx,
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)));
1008 result = winreg_printer_enumkeys(tmp_ctx,
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)));
1019 *pnum_subkeys = num_subkeys;
1021 *psubkeys = talloc_move(p->mem_ctx, &subkeys);
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);
1039 /* Delete a key with subkeys of a given printer. */
1040 WERROR winreg_delete_printer_key(struct pipes_struct *p,
1041 const char *printer,
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;
1050 TALLOC_CTX *tmp_ctx;
1052 tmp_ctx = talloc_new(p->mem_ctx);
1053 if (tmp_ctx == NULL) {
1057 path = winreg_printer_data_keyname(tmp_ctx, printer);
1059 TALLOC_FREE(tmp_ctx);
1063 result = winreg_printer_openkey(tmp_ctx,
1072 if (!W_ERROR_IS_OK(result)) {
1073 /* key doesn't exist */
1074 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1079 DEBUG(0, ("winreg_delete_printer_key: Could not open key %s: %s\n",
1080 key, win_errstr(result)));
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,
1092 if (keyname == NULL) {
1093 result = WERR_NOMEM;
1097 result = winreg_printer_delete_subkeys(tmp_ctx,
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)));
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);