s3-spoolss: Added a winreg_getform1 function.
[Samba/gebeck_regimport.git] / source3 / rpc_server / srv_spoolss_util.c
blobc3aafe395948480d6d708a74a928f8b924246462
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 /* FLAGS, NAME, with, height, left, top, right, bottom */
33 static const struct spoolss_FormInfo1 builtin_forms1[] = {
34 { SPOOLSS_FORM_BUILTIN, "Letter", {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
35 { SPOOLSS_FORM_BUILTIN, "Letter Small", {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
36 { SPOOLSS_FORM_BUILTIN, "Tabloid", {0x44368,0x696b8}, {0x0,0x0,0x44368,0x696b8} },
37 { SPOOLSS_FORM_BUILTIN, "Ledger", {0x696b8,0x44368}, {0x0,0x0,0x696b8,0x44368} },
38 { SPOOLSS_FORM_BUILTIN, "Legal", {0x34b5c,0x56d10}, {0x0,0x0,0x34b5c,0x56d10} },
39 { SPOOLSS_FORM_BUILTIN, "Statement", {0x221b4,0x34b5c}, {0x0,0x0,0x221b4,0x34b5c} },
40 { SPOOLSS_FORM_BUILTIN, "Executive", {0x2cf56,0x411cc}, {0x0,0x0,0x2cf56,0x411cc} },
41 { SPOOLSS_FORM_BUILTIN, "A3", {0x48828,0x668a0}, {0x0,0x0,0x48828,0x668a0} },
42 { SPOOLSS_FORM_BUILTIN, "A4", {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
43 { SPOOLSS_FORM_BUILTIN, "A4 Small", {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
44 { SPOOLSS_FORM_BUILTIN, "A5", {0x24220,0x33450}, {0x0,0x0,0x24220,0x33450} },
45 { SPOOLSS_FORM_BUILTIN, "B4 (JIS)", {0x3ebe8,0x58de0}, {0x0,0x0,0x3ebe8,0x58de0} },
46 { SPOOLSS_FORM_BUILTIN, "B5 (JIS)", {0x2c6f0,0x3ebe8}, {0x0,0x0,0x2c6f0,0x3ebe8} },
47 { SPOOLSS_FORM_BUILTIN, "Folio", {0x34b5c,0x509d8}, {0x0,0x0,0x34b5c,0x509d8} },
48 { SPOOLSS_FORM_BUILTIN, "Quarto", {0x347d8,0x43238}, {0x0,0x0,0x347d8,0x43238} },
49 { SPOOLSS_FORM_BUILTIN, "10x14", {0x3e030,0x56d10}, {0x0,0x0,0x3e030,0x56d10} },
50 { SPOOLSS_FORM_BUILTIN, "11x17", {0x44368,0x696b8}, {0x0,0x0,0x44368,0x696b8} },
51 { SPOOLSS_FORM_BUILTIN, "Note", {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
52 { SPOOLSS_FORM_BUILTIN, "Envelope #9", {0x18079,0x37091}, {0x0,0x0,0x18079,0x37091} },
53 { SPOOLSS_FORM_BUILTIN, "Envelope #10", {0x19947,0x3ae94}, {0x0,0x0,0x19947,0x3ae94} },
54 { SPOOLSS_FORM_BUILTIN, "Envelope #11", {0x1be7c,0x40565}, {0x0,0x0,0x1be7c,0x40565} },
55 { SPOOLSS_FORM_BUILTIN, "Envelope #12", {0x1d74a,0x44368}, {0x0,0x0,0x1d74a,0x44368} },
56 { SPOOLSS_FORM_BUILTIN, "Envelope #14", {0x1f018,0x47504}, {0x0,0x0,0x1f018,0x47504} },
57 { SPOOLSS_FORM_BUILTIN, "C size sheet", {0x696b8,0x886d0}, {0x0,0x0,0x696b8,0x886d0} },
58 { SPOOLSS_FORM_BUILTIN, "D size sheet", {0x886d0,0xd2d70}, {0x0,0x0,0x886d0,0xd2d70} },
59 { SPOOLSS_FORM_BUILTIN, "E size sheet", {0xd2d70,0x110da0},{0x0,0x0,0xd2d70,0x110da0} },
60 { SPOOLSS_FORM_BUILTIN, "Envelope DL", {0x1adb0,0x35b60}, {0x0,0x0,0x1adb0,0x35b60} },
61 { SPOOLSS_FORM_BUILTIN, "Envelope C5", {0x278d0,0x37e88}, {0x0,0x0,0x278d0,0x37e88} },
62 { SPOOLSS_FORM_BUILTIN, "Envelope C3", {0x4f1a0,0x6fd10}, {0x0,0x0,0x4f1a0,0x6fd10} },
63 { SPOOLSS_FORM_BUILTIN, "Envelope C4", {0x37e88,0x4f1a0}, {0x0,0x0,0x37e88,0x4f1a0} },
64 { SPOOLSS_FORM_BUILTIN, "Envelope C6", {0x1bd50,0x278d0}, {0x0,0x0,0x1bd50,0x278d0} },
65 { SPOOLSS_FORM_BUILTIN, "Envelope C65", {0x1bd50,0x37e88}, {0x0,0x0,0x1bd50,0x37e88} },
66 { SPOOLSS_FORM_BUILTIN, "Envelope B4", {0x3d090,0x562e8}, {0x0,0x0,0x3d090,0x562e8} },
67 { SPOOLSS_FORM_BUILTIN, "Envelope B5", {0x2af80,0x3d090}, {0x0,0x0,0x2af80,0x3d090} },
68 { SPOOLSS_FORM_BUILTIN, "Envelope B6", {0x2af80,0x1e848}, {0x0,0x0,0x2af80,0x1e848} },
69 { SPOOLSS_FORM_BUILTIN, "Envelope", {0x1adb0,0x38270}, {0x0,0x0,0x1adb0,0x38270} },
70 { SPOOLSS_FORM_BUILTIN, "Envelope Monarch", {0x18079,0x2e824}, {0x0,0x0,0x18079,0x2e824} },
71 { SPOOLSS_FORM_BUILTIN, "6 3/4 Envelope", {0x167ab,0x284ec}, {0x0,0x0,0x167ab,0x284ec} },
72 { SPOOLSS_FORM_BUILTIN, "US Std Fanfold", {0x5c3e1,0x44368}, {0x0,0x0,0x5c3e1,0x44368} },
73 { SPOOLSS_FORM_BUILTIN, "German Std Fanfold", {0x34b5c,0x4a6a0}, {0x0,0x0,0x34b5c,0x4a6a0} },
74 { SPOOLSS_FORM_BUILTIN, "German Legal Fanfold", {0x34b5c,0x509d8}, {0x0,0x0,0x34b5c,0x509d8} },
75 { SPOOLSS_FORM_BUILTIN, "B4 (ISO)", {0x3d090,0x562e8}, {0x0,0x0,0x3d090,0x562e8} },
76 { SPOOLSS_FORM_BUILTIN, "Japanese Postcard", {0x186a0,0x24220}, {0x0,0x0,0x186a0,0x24220} },
77 { SPOOLSS_FORM_BUILTIN, "9x11", {0x37cf8,0x44368}, {0x0,0x0,0x37cf8,0x44368} },
78 { SPOOLSS_FORM_BUILTIN, "10x11", {0x3e030,0x44368}, {0x0,0x0,0x3e030,0x44368} },
79 { SPOOLSS_FORM_BUILTIN, "15x11", {0x5d048,0x44368}, {0x0,0x0,0x5d048,0x44368} },
80 { SPOOLSS_FORM_BUILTIN, "Envelope Invite", {0x35b60,0x35b60}, {0x0,0x0,0x35b60,0x35b60} },
81 { SPOOLSS_FORM_BUILTIN, "Reserved48", {0x1,0x1}, {0x0,0x0,0x1,0x1} },
82 { SPOOLSS_FORM_BUILTIN, "Reserved49", {0x1,0x1}, {0x0,0x0,0x1,0x1} },
83 { SPOOLSS_FORM_BUILTIN, "Letter Extra", {0x3ae94,0x4a6a0}, {0x0,0x0,0x3ae94,0x4a6a0} },
84 { SPOOLSS_FORM_BUILTIN, "Legal Extra", {0x3ae94,0x5d048}, {0x0,0x0,0x3ae94,0x5d048} },
85 { SPOOLSS_FORM_BUILTIN, "Tabloid Extra", {0x4a6a0,0x6f9f0}, {0x0,0x0,0x4a6a0,0x6f9f0} },
86 { SPOOLSS_FORM_BUILTIN, "A4 Extra", {0x397c2,0x4eb16}, {0x0,0x0,0x397c2,0x4eb16} },
87 { SPOOLSS_FORM_BUILTIN, "Letter Transverse", {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
88 { SPOOLSS_FORM_BUILTIN, "A4 Transverse", {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
89 { SPOOLSS_FORM_BUILTIN, "Letter Extra Transverse", {0x3ae94,0x4a6a0}, {0x0,0x0,0x3ae94,0x4a6a0} },
90 { SPOOLSS_FORM_BUILTIN, "Super A", {0x376b8,0x56ea0}, {0x0,0x0,0x376b8,0x56ea0} },
91 { SPOOLSS_FORM_BUILTIN, "Super B", {0x4a768,0x76e58}, {0x0,0x0,0x4a768,0x76e58} },
92 { SPOOLSS_FORM_BUILTIN, "Letter Plus", {0x34b5c,0x4eb16}, {0x0,0x0,0x34b5c,0x4eb16} },
93 { SPOOLSS_FORM_BUILTIN, "A4 Plus", {0x33450,0x50910}, {0x0,0x0,0x33450,0x50910} },
94 { SPOOLSS_FORM_BUILTIN, "A5 Transverse", {0x24220,0x33450}, {0x0,0x0,0x24220,0x33450} },
95 { SPOOLSS_FORM_BUILTIN, "B5 (JIS) Transverse", {0x2c6f0,0x3ebe8}, {0x0,0x0,0x2c6f0,0x3ebe8} },
96 { SPOOLSS_FORM_BUILTIN, "A3 Extra", {0x4e9d0,0x6ca48}, {0x0,0x0,0x4e9d0,0x6ca48} },
97 { SPOOLSS_FORM_BUILTIN, "A5 Extra", {0x2a7b0,0x395f8}, {0x0,0x0,0x2a7b0,0x395f8} },
98 { SPOOLSS_FORM_BUILTIN, "B5 (ISO) Extra", {0x31128,0x43620}, {0x0,0x0,0x31128,0x43620} },
99 { SPOOLSS_FORM_BUILTIN, "A2", {0x668a0,0x91050}, {0x0,0x0,0x668a0,0x91050} },
100 { SPOOLSS_FORM_BUILTIN, "A3 Transverse", {0x48828,0x668a0}, {0x0,0x0,0x48828,0x668a0} },
101 { SPOOLSS_FORM_BUILTIN, "A3 Extra Transverse", {0x4e9d0,0x6ca48}, {0x0,0x0,0x4e9d0,0x6ca48} },
102 { SPOOLSS_FORM_BUILTIN, "Japanese Double Postcard", {0x30d40,0x24220}, {0x0,0x0,0x30d40,0x24220} },
103 { SPOOLSS_FORM_BUILTIN, "A6", {0x19a28,0x24220}, {0x0,0x0,0x19a28,0x24220} },
104 { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Kaku #2", {0x3a980,0x510e0}, {0x0,0x0,0x3a980,0x510e0} },
105 { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Kaku #3", {0x34bc0,0x43a08}, {0x0,0x0,0x34bc0,0x43a08} },
106 { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Chou #3", {0x1d4c0,0x395f8}, {0x0,0x0,0x1d4c0,0x395f8} },
107 { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Chou #4", {0x15f90,0x320c8}, {0x0,0x0,0x15f90,0x320c8} },
108 { SPOOLSS_FORM_BUILTIN, "Letter Rotated", {0x44368,0x34b5c}, {0x0,0x0,0x44368,0x34b5c} },
109 { SPOOLSS_FORM_BUILTIN, "A3 Rotated", {0x668a0,0x48828}, {0x0,0x0,0x668a0,0x48828} },
110 { SPOOLSS_FORM_BUILTIN, "A4 Rotated", {0x48828,0x33450}, {0x0,0x0,0x48828,0x33450} },
111 { SPOOLSS_FORM_BUILTIN, "A5 Rotated", {0x33450,0x24220}, {0x0,0x0,0x33450,0x24220} },
112 { SPOOLSS_FORM_BUILTIN, "B4 (JIS) Rotated", {0x58de0,0x3ebe8}, {0x0,0x0,0x58de0,0x3ebe8} },
113 { SPOOLSS_FORM_BUILTIN, "B5 (JIS) Rotated", {0x3ebe8,0x2c6f0}, {0x0,0x0,0x3ebe8,0x2c6f0} },
114 { SPOOLSS_FORM_BUILTIN, "Japanese Postcard Rotated", {0x24220,0x186a0}, {0x0,0x0,0x24220,0x186a0} },
115 { SPOOLSS_FORM_BUILTIN, "Double Japan Postcard Rotated", {0x24220,0x30d40}, {0x0,0x0,0x24220,0x30d40} },
116 { SPOOLSS_FORM_BUILTIN, "A6 Rotated", {0x24220,0x19a28}, {0x0,0x0,0x24220,0x19a28} },
117 { SPOOLSS_FORM_BUILTIN, "Japan Envelope Kaku #2 Rotated", {0x510e0,0x3a980}, {0x0,0x0,0x510e0,0x3a980} },
118 { SPOOLSS_FORM_BUILTIN, "Japan Envelope Kaku #3 Rotated", {0x43a08,0x34bc0}, {0x0,0x0,0x43a08,0x34bc0} },
119 { SPOOLSS_FORM_BUILTIN, "Japan Envelope Chou #3 Rotated", {0x395f8,0x1d4c0}, {0x0,0x0,0x395f8,0x1d4c0} },
120 { SPOOLSS_FORM_BUILTIN, "Japan Envelope Chou #4 Rotated", {0x320c8,0x15f90}, {0x0,0x0,0x320c8,0x15f90} },
121 { SPOOLSS_FORM_BUILTIN, "B6 (JIS)", {0x1f400,0x2c6f0}, {0x0,0x0,0x1f400,0x2c6f0} },
122 { SPOOLSS_FORM_BUILTIN, "B6 (JIS) Rotated", {0x2c6f0,0x1f400}, {0x0,0x0,0x2c6f0,0x1f400} },
123 { SPOOLSS_FORM_BUILTIN, "12x11", {0x4a724,0x443e1}, {0x0,0x0,0x4a724,0x443e1} },
124 { SPOOLSS_FORM_BUILTIN, "Japan Envelope You #4", {0x19a28,0x395f8}, {0x0,0x0,0x19a28,0x395f8} },
125 { SPOOLSS_FORM_BUILTIN, "Japan Envelope You #4 Rotated", {0x395f8,0x19a28}, {0x0,0x0,0x395f8,0x19a28} },
126 { SPOOLSS_FORM_BUILTIN, "PRC 16K", {0x2de60,0x3f7a0}, {0x0,0x0,0x2de60,0x3f7a0} },
127 { SPOOLSS_FORM_BUILTIN, "PRC 32K", {0x1fbd0,0x2cec0}, {0x0,0x0,0x1fbd0,0x2cec0} },
128 { SPOOLSS_FORM_BUILTIN, "PRC 32K(Big)", {0x222e0,0x318f8}, {0x0,0x0,0x222e0,0x318f8} },
129 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #1", {0x18e70,0x28488}, {0x0,0x0,0x18e70,0x28488} },
130 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #2", {0x18e70,0x2af80}, {0x0,0x0,0x18e70,0x2af80} },
131 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #3", {0x1e848,0x2af80}, {0x0,0x0,0x1e848,0x2af80} },
132 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #4", {0x1adb0,0x32c80}, {0x0,0x0,0x1adb0,0x32c80} },
133 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #5", {0x1adb0,0x35b60}, {0x0,0x0,0x1adb0,0x35b60} },
134 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #6", {0x1d4c0,0x38270}, {0x0,0x0,0x1d4c0,0x38270} },
135 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #7", {0x27100,0x38270}, {0x0,0x0,0x27100,0x38270} },
136 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #8", {0x1d4c0,0x4b708}, {0x0,0x0,0x1d4c0,0x4b708} },
137 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #9", {0x37e88,0x4f1a0}, {0x0,0x0,0x37e88,0x4f1a0} },
138 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #10", {0x4f1a0,0x6fd10}, {0x0,0x0,0x4f1a0,0x6fd10} },
139 { SPOOLSS_FORM_BUILTIN, "PRC 16K Rotated", {0x3f7a0,0x2de60}, {0x0,0x0,0x3f7a0,0x2de60} },
140 { SPOOLSS_FORM_BUILTIN, "PRC 32K Rotated", {0x2cec0,0x1fbd0}, {0x0,0x0,0x2cec0,0x1fbd0} },
141 { SPOOLSS_FORM_BUILTIN, "PRC 32K(Big) Rotated", {0x318f8,0x222e0}, {0x0,0x0,0x318f8,0x222e0} },
142 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #1 Rotated", {0x28488,0x18e70}, {0x0,0x0,0x28488,0x18e70} },
143 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #2 Rotated", {0x2af80,0x18e70}, {0x0,0x0,0x2af80,0x18e70} },
144 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #3 Rotated", {0x2af80,0x1e848}, {0x0,0x0,0x2af80,0x1e848} },
145 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #4 Rotated", {0x32c80,0x1adb0}, {0x0,0x0,0x32c80,0x1adb0} },
146 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #5 Rotated", {0x35b60,0x1adb0}, {0x0,0x0,0x35b60,0x1adb0} },
147 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #6 Rotated", {0x38270,0x1d4c0}, {0x0,0x0,0x38270,0x1d4c0} },
148 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #7 Rotated", {0x38270,0x27100}, {0x0,0x0,0x38270,0x27100} },
149 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #8 Rotated", {0x4b708,0x1d4c0}, {0x0,0x0,0x4b708,0x1d4c0} },
150 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #9 Rotated", {0x4f1a0,0x37e88}, {0x0,0x0,0x4f1a0,0x37e88} },
151 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #10 Rotated", {0x6fd10,0x4f1a0}, {0x0,0x0,0x6fd10,0x4f1a0} }
154 /********************************************************************
155 static helper functions
156 ********************************************************************/
159 * @internal
161 * @brief Connect to the interal winreg server and open the given printer key.
163 * The function will create the needed subkeys if they don't exist.
165 * @param[in] mem_ctx The memory context to use.
167 * @param[in] server_info The supplied server info.
169 * @param[out] winreg_pipe A pointer for the winreg rpc client pipe.
171 * @param[in] path The path to the key to open.
173 * @param[in] key The key to open.
175 * @param[in] create_key Set to true if the key should be created if it
176 * doesn't exist.
178 * @param[in] access_mask The access mask to open the key.
180 * @param[out] hive_handle A policy handle for the opened hive.
182 * @param[out] key_handle A policy handle for the opened key.
184 * @return WERR_OK on success, the corresponding DOS error
185 * code if something gone wrong.
187 static WERROR winreg_printer_openkey(TALLOC_CTX *mem_ctx,
188 struct auth_serversupplied_info *server_info,
189 struct rpc_pipe_client **winreg_pipe,
190 const char *path,
191 const char *key,
192 bool create_key,
193 uint32_t access_mask,
194 struct policy_handle *hive_handle,
195 struct policy_handle *key_handle)
197 struct rpc_pipe_client *pipe_handle;
198 struct winreg_String wkey, wkeyclass;
199 char *keyname;
200 NTSTATUS status;
201 WERROR result = WERR_OK;
203 /* create winreg connection */
204 status = rpc_pipe_open_internal(mem_ctx,
205 &ndr_table_winreg.syntax_id,
206 rpc_winreg_dispatch,
207 server_info,
208 &pipe_handle);
209 if (!NT_STATUS_IS_OK(status)) {
210 DEBUG(0, ("winreg_printer_openkey: Could not connect to winreg_pipe: %s\n",
211 nt_errstr(status)));
212 return ntstatus_to_werror(status);
215 status = rpccli_winreg_OpenHKLM(pipe_handle,
216 mem_ctx,
217 NULL,
218 access_mask,
219 hive_handle,
220 &result);
221 if (!NT_STATUS_IS_OK(status)) {
222 DEBUG(0, ("winreg_printer_openkey: Could not open HKLM hive: %s\n",
223 nt_errstr(status)));
224 talloc_free(pipe_handle);
225 if (!W_ERROR_IS_OK(result)) {
226 return result;
228 return ntstatus_to_werror(status);
231 if (key && *key) {
232 keyname = talloc_asprintf(mem_ctx, "%s\\%s", path, key);
233 } else {
234 keyname = talloc_strdup(mem_ctx, path);
236 if (keyname == NULL) {
237 talloc_free(pipe_handle);
238 return WERR_NOMEM;
241 ZERO_STRUCT(wkey);
242 wkey.name = keyname;
244 if (create_key) {
245 enum winreg_CreateAction action = REG_ACTION_NONE;
247 ZERO_STRUCT(wkeyclass);
248 wkeyclass.name = "";
250 status = rpccli_winreg_CreateKey(pipe_handle,
251 mem_ctx,
252 hive_handle,
253 wkey,
254 wkeyclass,
256 access_mask,
257 NULL,
258 key_handle,
259 &action,
260 &result);
261 switch (action) {
262 case REG_ACTION_NONE:
263 DEBUG(8, ("winreg_printer_openkey:createkey did nothing -- huh?\n"));
264 break;
265 case REG_CREATED_NEW_KEY:
266 DEBUG(8, ("winreg_printer_openkey: createkey created %s\n", keyname));
267 break;
268 case REG_OPENED_EXISTING_KEY:
269 DEBUG(8, ("winreg_printer_openkey: createkey opened existing %s\n", keyname));
270 break;
272 } else {
273 status = rpccli_winreg_OpenKey(pipe_handle,
274 mem_ctx,
275 hive_handle,
276 wkey,
278 access_mask,
279 key_handle,
280 &result);
282 if (!NT_STATUS_IS_OK(status)) {
283 talloc_free(pipe_handle);
284 if (!W_ERROR_IS_OK(result)) {
285 return result;
287 return ntstatus_to_werror(status);
290 *winreg_pipe = pipe_handle;
292 return WERR_OK;
296 * @brief Create the registry keyname for the given printer.
298 * @param[in] mem_ctx The memory context to use.
300 * @param[in] printer The name of the printer to get the registry key.
302 * @return The registry key or NULL on error.
304 static char *winreg_printer_data_keyname(TALLOC_CTX *mem_ctx, const char *printer) {
305 return talloc_asprintf(mem_ctx, "%s\\%s", TOP_LEVEL_PRINT_PRINTERS_KEY, printer);
309 * @internal
311 * @brief Enumerate values of an opened key handle and retrieve the data.
313 * @param[in] mem_ctx The memory context to use.
315 * @param[in] pipe_handle The pipe handle for the rpc connection.
317 * @param[in] key_hnd The opened key handle.
319 * @param[out] pnum_values A pointer to store he number of values found.
321 * @param[out] pnum_values A pointer to store the number of values we found.
323 * @return WERR_OK on success, the corresponding DOS error
324 * code if something gone wrong.
326 static WERROR winreg_printer_enumvalues(TALLOC_CTX *mem_ctx,
327 struct rpc_pipe_client *pipe_handle,
328 struct policy_handle *key_hnd,
329 uint32_t *pnum_values,
330 struct spoolss_PrinterEnumValues **penum_values)
332 TALLOC_CTX *tmp_ctx;
333 uint32_t num_subkeys, max_subkeylen, max_classlen;
334 uint32_t num_values, max_valnamelen, max_valbufsize;
335 uint32_t secdescsize;
336 uint32_t i;
337 NTTIME last_changed_time;
338 struct winreg_String classname;
340 struct spoolss_PrinterEnumValues *enum_values;
342 WERROR result = WERR_OK;
343 NTSTATUS status;
345 tmp_ctx = talloc_new(mem_ctx);
346 if (tmp_ctx == NULL) {
347 return WERR_NOMEM;
350 ZERO_STRUCT(classname);
352 status = rpccli_winreg_QueryInfoKey(pipe_handle,
353 tmp_ctx,
354 key_hnd,
355 &classname,
356 &num_subkeys,
357 &max_subkeylen,
358 &max_classlen,
359 &num_values,
360 &max_valnamelen,
361 &max_valbufsize,
362 &secdescsize,
363 &last_changed_time,
364 &result);
365 if (!NT_STATUS_IS_OK(status)) {
366 DEBUG(0, ("winreg_printer_enumvalues: Could not query info: %s\n",
367 nt_errstr(status)));
368 if (!W_ERROR_IS_OK(result)) {
369 goto error;
371 result = ntstatus_to_werror(status);
372 goto error;
375 if (num_values == 0) {
376 *pnum_values = 0;
377 TALLOC_FREE(tmp_ctx);
378 return WERR_OK;
381 enum_values = TALLOC_ARRAY(tmp_ctx, struct spoolss_PrinterEnumValues, num_values);
382 if (enum_values == NULL) {
383 result = WERR_NOMEM;
384 goto error;
387 for (i = 0; i < num_values; i++) {
388 struct spoolss_PrinterEnumValues val;
389 struct winreg_ValNameBuf name_buf;
390 enum winreg_Type type = REG_NONE;
391 uint8_t *data = NULL;
392 uint32_t data_size;
393 uint32_t length;
394 char n = '\0';;
396 name_buf.name = &n;
397 name_buf.size = max_valnamelen + 2;
398 name_buf.length = 0;
400 data_size = max_valbufsize;
401 data = (uint8_t *) TALLOC(tmp_ctx, data_size);
402 length = 0;
404 status = rpccli_winreg_EnumValue(pipe_handle,
405 tmp_ctx,
406 key_hnd,
408 &name_buf,
409 &type,
410 data,
411 &data_size,
412 &length,
413 &result);
414 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
415 result = WERR_OK;
416 status = NT_STATUS_OK;
417 break;
420 if (!NT_STATUS_IS_OK(status)) {
421 DEBUG(0, ("winreg_printer_enumvalues: Could not enumerate values: %s\n",
422 nt_errstr(status)));
423 if (!W_ERROR_IS_OK(result)) {
424 goto error;
426 result = ntstatus_to_werror(status);
427 goto error;
430 if (name_buf.name == NULL) {
431 result = WERR_INVALID_PARAMETER;
432 goto error;
435 val.value_name = talloc_strdup(enum_values, name_buf.name);
436 if (val.value_name == NULL) {
437 result = WERR_NOMEM;
438 goto error;
440 val.value_name_len = strlen_m_term(val.value_name) * 2;
442 val.type = type;
443 val.data_length = data_size;
444 if (val.data_length) {
445 val.data = talloc(enum_values, DATA_BLOB);
446 if (val.data == NULL) {
447 result = WERR_NOMEM;
448 goto error;
450 *val.data = data_blob_talloc(enum_values, data, data_size);
453 enum_values[i] = val;
456 *pnum_values = num_values;
457 if (penum_values) {
458 *penum_values = talloc_move(mem_ctx, &enum_values);
461 result = WERR_OK;
463 error:
464 TALLOC_FREE(tmp_ctx);
465 return result;
469 * @internal
471 * @brief Enumerate subkeys of an opened key handle and get the names.
473 * @param[in] mem_ctx The memory context to use.
475 * @param[in] pipe_handle The pipe handle for the rpc connection.
477 * @param[in] key_hnd The opened key handle.
479 * @param[in] pnum_subkeys A pointer to store the number of found subkeys.
481 * @param[in] psubkeys A pointer to an array to store the found names of
482 * subkeys.
484 * @return WERR_OK on success, the corresponding DOS error
485 * code if something gone wrong.
487 static WERROR winreg_printer_enumkeys(TALLOC_CTX *mem_ctx,
488 struct rpc_pipe_client *pipe_handle,
489 struct policy_handle *key_hnd,
490 uint32_t *pnum_subkeys,
491 const char ***psubkeys)
493 TALLOC_CTX *tmp_ctx;
494 const char **subkeys;
495 uint32_t num_subkeys, max_subkeylen, max_classlen;
496 uint32_t num_values, max_valnamelen, max_valbufsize;
497 uint32_t i;
498 NTTIME last_changed_time;
499 uint32_t secdescsize;
500 struct winreg_String classname;
501 WERROR result = WERR_OK;
502 NTSTATUS status;
504 tmp_ctx = talloc_new(mem_ctx);
505 if (tmp_ctx == NULL) {
506 return WERR_NOMEM;
509 ZERO_STRUCT(classname);
511 status = rpccli_winreg_QueryInfoKey(pipe_handle,
512 tmp_ctx,
513 key_hnd,
514 &classname,
515 &num_subkeys,
516 &max_subkeylen,
517 &max_classlen,
518 &num_values,
519 &max_valnamelen,
520 &max_valbufsize,
521 &secdescsize,
522 &last_changed_time,
523 &result);
524 if (!NT_STATUS_IS_OK(status)) {
525 DEBUG(0, ("winreg_printer_enumkeys: Could not query info: %s\n",
526 nt_errstr(status)));
527 if (!W_ERROR_IS_OK(result)) {
528 goto error;
530 result = ntstatus_to_werror(status);
531 goto error;
534 subkeys = talloc_zero_array(tmp_ctx, const char *, num_subkeys + 2);
535 if (subkeys == NULL) {
536 result = WERR_NOMEM;
537 goto error;
540 if (num_subkeys == 0) {
541 subkeys[0] = talloc_strdup(subkeys, "");
542 if (subkeys[0] == NULL) {
543 result = WERR_NOMEM;
544 goto error;
546 *pnum_subkeys = 0;
547 if (psubkeys) {
548 *psubkeys = talloc_move(mem_ctx, &subkeys);
551 TALLOC_FREE(tmp_ctx);
552 return WERR_OK;
555 for (i = 0; i < num_subkeys; i++) {
556 char c = '\0';
557 char n = '\0';
558 char *name = NULL;
559 struct winreg_StringBuf class_buf;
560 struct winreg_StringBuf name_buf;
561 NTTIME modtime;
563 class_buf.name = &c;
564 class_buf.size = max_classlen + 2;
565 class_buf.length = 0;
567 name_buf.name = &n;
568 name_buf.size = max_subkeylen + 2;
569 name_buf.length = 0;
571 ZERO_STRUCT(modtime);
573 status = rpccli_winreg_EnumKey(pipe_handle,
574 tmp_ctx,
575 key_hnd,
577 &name_buf,
578 &class_buf,
579 &modtime,
580 &result);
581 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
582 result = WERR_OK;
583 status = NT_STATUS_OK;
584 break;
587 if (!NT_STATUS_IS_OK(status)) {
588 DEBUG(0, ("winreg_printer_enumkeys: Could not enumerate keys: %s\n",
589 nt_errstr(status)));
590 if (!W_ERROR_IS_OK(result)) {
591 goto error;
593 result = ntstatus_to_werror(status);
594 goto error;
597 if (name_buf.name == NULL) {
598 result = WERR_INVALID_PARAMETER;
599 goto error;
602 name = talloc_strdup(subkeys, name_buf.name);
603 if (name == NULL) {
604 result = WERR_NOMEM;
605 goto error;
608 subkeys[i] = name;
611 *pnum_subkeys = num_subkeys;
612 if (psubkeys) {
613 *psubkeys = talloc_move(mem_ctx, &subkeys);
616 error:
617 TALLOC_FREE(tmp_ctx);
618 return result;
622 * @internal
624 * @brief A function to delete a key and its subkeys recurively.
626 * @param[in] mem_ctx The memory context to use.
628 * @param[in] pipe_handle The pipe handle for the rpc connection.
630 * @param[in] hive_handle A opened hive handle to the key.
632 * @param[in] access_mask The access mask to access the key.
634 * @param[in] key The key to delete
636 * @return WERR_OK on success, the corresponding DOS error
637 * code if something gone wrong.
639 static WERROR winreg_printer_delete_subkeys(TALLOC_CTX *mem_ctx,
640 struct rpc_pipe_client *pipe_handle,
641 struct policy_handle *hive_handle,
642 uint32_t access_mask,
643 const char *key)
645 const char **subkeys = NULL;
646 uint32_t num_subkeys = 0;
647 struct policy_handle key_hnd;
648 struct winreg_String wkey;
649 WERROR result = WERR_OK;
650 NTSTATUS status;
651 uint32_t i;
653 ZERO_STRUCT(key_hnd);
654 wkey.name = key;
656 DEBUG(2, ("winreg_printer_delete_subkeys: delete key %s\n", key));
657 /* open the key */
658 status = rpccli_winreg_OpenKey(pipe_handle,
659 mem_ctx,
660 hive_handle,
661 wkey,
663 access_mask,
664 &key_hnd,
665 &result);
666 if (!NT_STATUS_IS_OK(status)) {
667 DEBUG(0, ("winreg_printer_delete_subkeys: Could not open key %s: %s\n",
668 wkey.name, nt_errstr(status)));
669 if (!W_ERROR_IS_OK(result)) {
670 return result;
672 return ntstatus_to_werror(status);
675 result = winreg_printer_enumkeys(mem_ctx,
676 pipe_handle,
677 &key_hnd,
678 &num_subkeys,
679 &subkeys);
680 if (!W_ERROR_IS_OK(result)) {
681 goto done;
684 for (i = 0; i < num_subkeys; i++) {
685 /* create key + subkey */
686 char *subkey = talloc_asprintf(mem_ctx, "%s\\%s", key, subkeys[i]);
687 if (subkey == NULL) {
688 goto done;
691 DEBUG(2, ("winreg_printer_delete_subkeys: delete subkey %s\n", subkey));
692 result = winreg_printer_delete_subkeys(mem_ctx,
693 pipe_handle,
694 hive_handle,
695 access_mask,
696 subkey);
697 if (!W_ERROR_IS_OK(result)) {
698 goto done;
702 if (is_valid_policy_hnd(&key_hnd)) {
703 rpccli_winreg_CloseKey(pipe_handle, mem_ctx, &key_hnd, NULL);
706 wkey.name = key;
708 status = rpccli_winreg_DeleteKey(pipe_handle,
709 mem_ctx,
710 hive_handle,
711 wkey,
712 &result);
714 done:
715 if (is_valid_policy_hnd(&key_hnd)) {
716 rpccli_winreg_CloseKey(pipe_handle, mem_ctx, &key_hnd, NULL);
719 return result;
722 /********************************************************************
723 Public winreg function for spoolss
724 ********************************************************************/
726 /* Set printer data over the winreg pipe. */
727 WERROR winreg_set_printer_dataex(struct pipes_struct *p,
728 const char *printer,
729 const char *key,
730 const char *value,
731 enum winreg_Type type,
732 uint8_t *data,
733 uint32_t data_size)
735 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
736 struct rpc_pipe_client *winreg_pipe = NULL;
737 struct policy_handle hive_hnd, key_hnd;
738 struct winreg_String wvalue;
739 char *path;
740 WERROR result = WERR_OK;
741 NTSTATUS status;
742 TALLOC_CTX *tmp_ctx;
744 tmp_ctx = talloc_new(p->mem_ctx);
745 if (tmp_ctx == NULL) {
746 return WERR_NOMEM;
749 path = winreg_printer_data_keyname(tmp_ctx, printer);
750 if (path == NULL) {
751 TALLOC_FREE(tmp_ctx);
752 return WERR_NOMEM;
755 ZERO_STRUCT(hive_hnd);
756 ZERO_STRUCT(key_hnd);
758 DEBUG(8, ("winreg_set_printer_dataex: Open printer key %s, value %s, access_mask: 0x%05x for [%s]\n",
759 key, value, access_mask, printer));
760 result = winreg_printer_openkey(tmp_ctx,
761 p->server_info,
762 &winreg_pipe,
763 path,
764 key,
765 true,
766 access_mask,
767 &hive_hnd,
768 &key_hnd);
769 if (!W_ERROR_IS_OK(result)) {
770 DEBUG(0, ("winreg_set_printer_dataex: Could not open key %s: %s\n",
771 key, win_errstr(result)));
772 goto done;
775 wvalue.name = value;
776 status = rpccli_winreg_SetValue(winreg_pipe,
777 tmp_ctx,
778 &key_hnd,
779 wvalue,
780 type,
781 data,
782 data_size,
783 &result);
784 if (!NT_STATUS_IS_OK(status)) {
785 DEBUG(0, ("winreg_set_printer_dataex: Could not set value %s: %s\n",
786 value, nt_errstr(status)));
787 if (!W_ERROR_IS_OK(result)) {
788 goto done;
790 result = ntstatus_to_werror(status);
791 goto done;
794 result = WERR_OK;
795 done:
796 if (winreg_pipe != NULL) {
797 if (is_valid_policy_hnd(&key_hnd)) {
798 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
800 if (is_valid_policy_hnd(&hive_hnd)) {
801 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
805 TALLOC_FREE(tmp_ctx);
806 return result;
809 /* Get printer data over a winreg pipe. */
810 WERROR winreg_get_printer_dataex(struct pipes_struct *p,
811 const char *printer,
812 const char *key,
813 const char *value,
814 enum winreg_Type *type,
815 uint8_t **data,
816 uint32_t *data_size)
818 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
819 struct rpc_pipe_client *winreg_pipe = NULL;
820 struct policy_handle hive_hnd, key_hnd;
821 struct winreg_String wvalue;
822 enum winreg_Type type_in;
823 char *path;
824 uint8_t *data_in;
825 uint32_t data_in_size = 0;
826 uint32_t value_len = 0;
827 WERROR result = WERR_OK;
828 NTSTATUS status;
829 TALLOC_CTX *tmp_ctx;
831 tmp_ctx = talloc_new(p->mem_ctx);
832 if (tmp_ctx == NULL) {
833 return WERR_NOMEM;
836 path = winreg_printer_data_keyname(tmp_ctx, printer);
837 if (path == NULL) {
838 TALLOC_FREE(tmp_ctx);
839 return WERR_NOMEM;
842 ZERO_STRUCT(hive_hnd);
843 ZERO_STRUCT(key_hnd);
845 result = winreg_printer_openkey(tmp_ctx,
846 p->server_info,
847 &winreg_pipe,
848 path,
849 key,
850 false,
851 access_mask,
852 &hive_hnd,
853 &key_hnd);
854 if (!W_ERROR_IS_OK(result)) {
855 DEBUG(0, ("winreg_get_printer_dataex: Could not open key %s: %s\n",
856 key, win_errstr(result)));
857 goto done;
860 wvalue.name = value;
863 * call QueryValue once with data == NULL to get the
864 * needed memory size to be allocated, then allocate
865 * data buffer and call again.
867 status = rpccli_winreg_QueryValue(winreg_pipe,
868 tmp_ctx,
869 &key_hnd,
870 &wvalue,
871 &type_in,
872 NULL,
873 &data_in_size,
874 &value_len,
875 &result);
876 if (!NT_STATUS_IS_OK(status)) {
877 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
878 value, nt_errstr(status)));
879 if (!W_ERROR_IS_OK(result)) {
880 goto done;
882 result = ntstatus_to_werror(status);
883 goto done;
886 data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
887 if (data_in == NULL) {
888 result = WERR_NOMEM;
889 goto done;
891 value_len = 0;
893 status = rpccli_winreg_QueryValue(winreg_pipe,
894 tmp_ctx,
895 &key_hnd,
896 &wvalue,
897 &type_in,
898 data_in,
899 &data_in_size,
900 &value_len,
901 &result);
902 if (!NT_STATUS_IS_OK(status)) {
903 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
904 value, nt_errstr(status)));
905 if (!W_ERROR_IS_OK(result)) {
906 result = ntstatus_to_werror(status);
908 goto done;
911 *type = type_in;
912 *data_size = data_in_size;
913 if (data_in_size) {
914 *data = talloc_move(p->mem_ctx, &data_in);
917 result = WERR_OK;
918 done:
919 if (winreg_pipe != NULL) {
920 if (is_valid_policy_hnd(&key_hnd)) {
921 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
923 if (is_valid_policy_hnd(&hive_hnd)) {
924 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
928 TALLOC_FREE(tmp_ctx);
929 return result;
932 /* Enumerate on the values of a given key and provide the data. */
933 WERROR winreg_enum_printer_dataex(struct pipes_struct *p,
934 const char *printer,
935 const char *key,
936 uint32_t *pnum_values,
937 struct spoolss_PrinterEnumValues **penum_values)
939 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
940 struct rpc_pipe_client *winreg_pipe = NULL;
941 struct policy_handle hive_hnd, key_hnd;
943 struct spoolss_PrinterEnumValues *enum_values = NULL;
944 uint32_t num_values = 0;
945 char *path;
946 WERROR result = WERR_OK;
948 TALLOC_CTX *tmp_ctx;
950 tmp_ctx = talloc_new(p->mem_ctx);
951 if (tmp_ctx == NULL) {
952 return WERR_NOMEM;
955 path = winreg_printer_data_keyname(tmp_ctx, printer);
956 if (path == NULL) {
957 TALLOC_FREE(tmp_ctx);
958 return WERR_NOMEM;
961 result = winreg_printer_openkey(tmp_ctx,
962 p->server_info,
963 &winreg_pipe,
964 path,
965 key,
966 false,
967 access_mask,
968 &hive_hnd,
969 &key_hnd);
970 if (!W_ERROR_IS_OK(result)) {
971 DEBUG(0, ("winreg_enum_printer_dataex: Could not open key %s: %s\n",
972 key, win_errstr(result)));
973 goto done;
976 result = winreg_printer_enumvalues(tmp_ctx,
977 winreg_pipe,
978 &key_hnd,
979 &num_values,
980 &enum_values);
981 if (!W_ERROR_IS_OK(result)) {
982 DEBUG(0, ("winreg_enum_printer_dataex: Could not enumerate values in %s: %s\n",
983 key, win_errstr(result)));
984 goto done;
987 *pnum_values = num_values;
988 if (penum_values) {
989 *penum_values = talloc_move(p->mem_ctx, &enum_values);
992 result = WERR_OK;
993 done:
994 if (winreg_pipe != NULL) {
995 if (is_valid_policy_hnd(&key_hnd)) {
996 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
998 if (is_valid_policy_hnd(&hive_hnd)) {
999 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1003 TALLOC_FREE(tmp_ctx);
1004 return result;
1007 /* Delete printer data over a winreg pipe. */
1008 WERROR winreg_delete_printer_dataex(struct pipes_struct *p,
1009 const char *printer,
1010 const char *key,
1011 const char *value)
1013 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1014 struct rpc_pipe_client *winreg_pipe = NULL;
1015 struct policy_handle hive_hnd, key_hnd;
1016 struct winreg_String wvalue;
1017 char *path;
1018 WERROR result = WERR_OK;
1019 NTSTATUS status;
1021 TALLOC_CTX *tmp_ctx;
1023 tmp_ctx = talloc_new(p->mem_ctx);
1024 if (tmp_ctx == NULL) {
1025 return WERR_NOMEM;
1028 path = winreg_printer_data_keyname(tmp_ctx, printer);
1029 if (path == NULL) {
1030 TALLOC_FREE(tmp_ctx);
1031 return WERR_NOMEM;
1034 ZERO_STRUCT(hive_hnd);
1035 ZERO_STRUCT(key_hnd);
1037 result = winreg_printer_openkey(tmp_ctx,
1038 p->server_info,
1039 &winreg_pipe,
1040 path,
1041 key,
1042 false,
1043 access_mask,
1044 &hive_hnd,
1045 &key_hnd);
1046 if (!W_ERROR_IS_OK(result)) {
1047 DEBUG(0, ("winreg_delete_printer_dataex: Could not open key %s: %s\n",
1048 key, win_errstr(result)));
1049 goto done;
1052 wvalue.name = value;
1053 status = rpccli_winreg_DeleteValue(winreg_pipe,
1054 tmp_ctx,
1055 &key_hnd,
1056 wvalue,
1057 &result);
1058 if (!NT_STATUS_IS_OK(status)) {
1059 DEBUG(0, ("winreg_delete_printer_dataex: Could not delete value %s: %s\n",
1060 value, nt_errstr(status)));
1061 if (!W_ERROR_IS_OK(result)) {
1062 goto done;
1064 result = ntstatus_to_werror(status);
1065 goto done;
1068 result = WERR_OK;
1069 done:
1070 if (winreg_pipe != NULL) {
1071 if (is_valid_policy_hnd(&key_hnd)) {
1072 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1074 if (is_valid_policy_hnd(&hive_hnd)) {
1075 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1079 TALLOC_FREE(tmp_ctx);
1080 return result;
1083 /* Enumerate on the subkeys of a given key and provide the data. */
1084 WERROR winreg_enum_printer_key(struct pipes_struct *p,
1085 const char *printer,
1086 const char *key,
1087 uint32_t *pnum_subkeys,
1088 const char ***psubkeys)
1090 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1091 struct rpc_pipe_client *winreg_pipe = NULL;
1092 struct policy_handle hive_hnd, key_hnd;
1093 char *path;
1094 const char **subkeys = NULL;
1095 uint32_t num_subkeys = -1;
1097 WERROR result = WERR_OK;
1099 TALLOC_CTX *tmp_ctx;
1101 tmp_ctx = talloc_new(p->mem_ctx);
1102 if (tmp_ctx == NULL) {
1103 return WERR_NOMEM;
1106 path = winreg_printer_data_keyname(tmp_ctx, printer);
1107 if (path == NULL) {
1108 TALLOC_FREE(tmp_ctx);
1109 return WERR_NOMEM;
1112 ZERO_STRUCT(hive_hnd);
1113 ZERO_STRUCT(key_hnd);
1115 result = winreg_printer_openkey(tmp_ctx,
1116 p->server_info,
1117 &winreg_pipe,
1118 path,
1119 key,
1120 false,
1121 access_mask,
1122 &hive_hnd,
1123 &key_hnd);
1124 if (!W_ERROR_IS_OK(result)) {
1125 DEBUG(0, ("winreg_enum_printer_key: Could not open key %s: %s\n",
1126 key, win_errstr(result)));
1127 goto done;
1130 result = winreg_printer_enumkeys(tmp_ctx,
1131 winreg_pipe,
1132 &key_hnd,
1133 &num_subkeys,
1134 &subkeys);
1135 if (!W_ERROR_IS_OK(result)) {
1136 DEBUG(0, ("winreg_enum_printer_key: Could not enumerate subkeys in %s: %s\n",
1137 key, win_errstr(result)));
1138 goto done;
1141 *pnum_subkeys = num_subkeys;
1142 if (psubkeys) {
1143 *psubkeys = talloc_move(p->mem_ctx, &subkeys);
1146 result = WERR_OK;
1147 done:
1148 if (winreg_pipe != NULL) {
1149 if (is_valid_policy_hnd(&key_hnd)) {
1150 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1152 if (is_valid_policy_hnd(&hive_hnd)) {
1153 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1157 TALLOC_FREE(tmp_ctx);
1158 return result;
1161 /* Delete a key with subkeys of a given printer. */
1162 WERROR winreg_delete_printer_key(struct pipes_struct *p,
1163 const char *printer,
1164 const char *key)
1166 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1167 struct rpc_pipe_client *winreg_pipe = NULL;
1168 struct policy_handle hive_hnd, key_hnd;
1169 char *keyname;
1170 char *path;
1171 WERROR result;
1172 TALLOC_CTX *tmp_ctx;
1174 tmp_ctx = talloc_new(p->mem_ctx);
1175 if (tmp_ctx == NULL) {
1176 return WERR_NOMEM;
1179 path = winreg_printer_data_keyname(tmp_ctx, printer);
1180 if (path == NULL) {
1181 TALLOC_FREE(tmp_ctx);
1182 return WERR_NOMEM;
1185 result = winreg_printer_openkey(tmp_ctx,
1186 p->server_info,
1187 &winreg_pipe,
1188 path,
1189 key,
1190 false,
1191 access_mask,
1192 &hive_hnd,
1193 &key_hnd);
1194 if (!W_ERROR_IS_OK(result)) {
1195 /* key doesn't exist */
1196 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1197 result = WERR_OK;
1198 goto done;
1201 DEBUG(0, ("winreg_delete_printer_key: Could not open key %s: %s\n",
1202 key, win_errstr(result)));
1203 goto done;
1206 if (is_valid_policy_hnd(&key_hnd)) {
1207 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1210 keyname = talloc_asprintf(tmp_ctx,
1211 "%s\\%s",
1212 path,
1213 key);
1214 if (keyname == NULL) {
1215 result = WERR_NOMEM;
1216 goto done;
1219 result = winreg_printer_delete_subkeys(tmp_ctx,
1220 winreg_pipe,
1221 &hive_hnd,
1222 access_mask,
1223 keyname);
1224 if (!W_ERROR_IS_OK(result)) {
1225 DEBUG(0, ("winreg_delete_printer_key: Could not delete key %s: %s\n",
1226 key, win_errstr(result)));
1227 goto done;
1230 done:
1231 if (winreg_pipe != NULL) {
1232 if (is_valid_policy_hnd(&key_hnd)) {
1233 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1235 if (is_valid_policy_hnd(&hive_hnd)) {
1236 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1240 TALLOC_FREE(tmp_ctx);
1241 return result;
1245 * The special behaviour of the spoolss forms is documented at the website:
1247 * Managing Win32 Printserver Forms
1248 * http://unixwiz.net/techtips/winspooler-forms.html
1251 WERROR winreg_printer_addform1(struct pipes_struct *p,
1252 struct spoolss_AddFormInfo1 *form)
1254 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1255 struct rpc_pipe_client *winreg_pipe = NULL;
1256 struct policy_handle hive_hnd, key_hnd;
1257 struct winreg_String wvalue;
1258 DATA_BLOB blob;
1259 uint32_t num_info = 0;
1260 union spoolss_FormInfo *info = NULL;
1261 uint32_t i;
1262 WERROR result;
1263 NTSTATUS status;
1264 TALLOC_CTX *tmp_ctx;
1266 tmp_ctx = talloc_new(p->mem_ctx);
1267 if (tmp_ctx == NULL) {
1268 return WERR_NOMEM;
1271 ZERO_STRUCT(hive_hnd);
1272 ZERO_STRUCT(key_hnd);
1274 result = winreg_printer_openkey(tmp_ctx,
1275 p->server_info,
1276 &winreg_pipe,
1277 TOP_LEVEL_CONTROL_FORMS_KEY,
1279 true,
1280 access_mask,
1281 &hive_hnd,
1282 &key_hnd);
1283 if (!W_ERROR_IS_OK(result)) {
1284 DEBUG(0, ("winreg_printer_addform1: Could not open key %s: %s\n",
1285 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
1286 goto done;
1289 result = winreg_printer_enumforms1(p, &num_info, &info);
1290 if (!W_ERROR_IS_OK(result)) {
1291 DEBUG(0, ("winreg_printer_addform: Could not enum keys %s: %s\n",
1292 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
1293 goto done;
1296 /* If form name already exists or is builtin return ALREADY_EXISTS */
1297 for (i = 0; i < num_info; i++) {
1298 if (strequal(info[i].info1.form_name, form->form_name)) {
1299 result = WERR_FILE_EXISTS;
1300 goto done;
1304 wvalue.name = form->form_name;
1306 blob = data_blob_talloc(tmp_ctx, NULL, 32);
1307 SIVAL(blob.data, 0, form->size.width);
1308 SIVAL(blob.data, 4, form->size.height);
1309 SIVAL(blob.data, 8, form->area.left);
1310 SIVAL(blob.data, 12, form->area.top);
1311 SIVAL(blob.data, 16, form->area.right);
1312 SIVAL(blob.data, 20, form->area.bottom);
1313 SIVAL(blob.data, 24, num_info + 1); /* FIXME */
1314 SIVAL(blob.data, 28, form->flags);
1316 status = rpccli_winreg_SetValue(winreg_pipe,
1317 tmp_ctx,
1318 &key_hnd,
1319 wvalue,
1320 REG_BINARY,
1321 blob.data,
1322 blob.length,
1323 &result);
1324 if (!NT_STATUS_IS_OK(status)) {
1325 DEBUG(0, ("winreg_printer_addform1: Could not set value %s: %s\n",
1326 wvalue.name, nt_errstr(status)));
1327 if (!W_ERROR_IS_OK(result)) {
1328 goto done;
1330 result = ntstatus_to_werror(status);
1331 goto done;
1334 result = WERR_OK;
1335 done:
1336 if (winreg_pipe != NULL) {
1337 if (is_valid_policy_hnd(&key_hnd)) {
1338 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1340 if (is_valid_policy_hnd(&hive_hnd)) {
1341 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1345 TALLOC_FREE(info);
1346 TALLOC_FREE(tmp_ctx);
1347 return result;
1350 WERROR winreg_printer_enumforms1(struct pipes_struct *p,
1351 uint32_t *pnum_info,
1352 union spoolss_FormInfo **pinfo)
1354 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1355 struct rpc_pipe_client *winreg_pipe = NULL;
1356 struct policy_handle hive_hnd, key_hnd;
1357 union spoolss_FormInfo *info;
1358 struct spoolss_PrinterEnumValues *enum_values = NULL;
1359 uint32_t num_values = 0;
1360 uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
1361 uint32_t i;
1362 WERROR result;
1363 TALLOC_CTX *tmp_ctx;
1365 tmp_ctx = talloc_new(p->mem_ctx);
1366 if (tmp_ctx == NULL) {
1367 return WERR_NOMEM;
1370 ZERO_STRUCT(hive_hnd);
1371 ZERO_STRUCT(key_hnd);
1373 result = winreg_printer_openkey(tmp_ctx,
1374 p->server_info,
1375 &winreg_pipe,
1376 TOP_LEVEL_CONTROL_FORMS_KEY,
1378 true,
1379 access_mask,
1380 &hive_hnd,
1381 &key_hnd);
1382 if (!W_ERROR_IS_OK(result)) {
1383 /* key doesn't exist */
1384 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1385 result = WERR_OK;
1386 goto done;
1389 DEBUG(0, ("winreg_printer_enumforms1: Could not open key %s: %s\n",
1390 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
1391 goto done;
1394 result = winreg_printer_enumvalues(tmp_ctx,
1395 winreg_pipe,
1396 &key_hnd,
1397 &num_values,
1398 &enum_values);
1399 if (!W_ERROR_IS_OK(result)) {
1400 DEBUG(0, ("winreg_printer_enumforms1: Could not enumerate values in %s: %s\n",
1401 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
1402 goto done;
1405 info = TALLOC_ARRAY(tmp_ctx, union spoolss_FormInfo, num_builtin + num_values);
1406 if (info == NULL) {
1407 result = WERR_NOMEM;
1408 goto done;
1411 /* Enumerate BUILTIN forms */
1412 for (i = 0; i < num_builtin; i++) {
1413 info[i].info1 = builtin_forms1[i];
1416 /* Enumerate registry forms */
1417 for (i = 0; i < num_values; i++) {
1418 union spoolss_FormInfo val;
1420 if (enum_values[i].type != REG_BINARY ||
1421 enum_values[i].data_length != 32) {
1422 continue;
1425 val.info1.form_name = talloc_strdup(info, enum_values[i].value_name);
1426 if (val.info1.form_name == NULL) {
1427 result = WERR_NOMEM;
1428 goto done;
1431 val.info1.size.width = IVAL(enum_values[i].data->data, 0);
1432 val.info1.size.height = IVAL(enum_values[i].data->data, 4);
1433 val.info1.area.left = IVAL(enum_values[i].data->data, 8);
1434 val.info1.area.top = IVAL(enum_values[i].data->data, 12);
1435 val.info1.area.right = IVAL(enum_values[i].data->data, 16);
1436 val.info1.area.bottom = IVAL(enum_values[i].data->data, 20);
1437 /* skip form index IVAL(enum_values[i].data->data, 24)));*/
1438 val.info1.flags = IVAL(enum_values[i].data->data, 28);
1440 info[i + num_builtin] = val;
1443 *pnum_info = num_builtin + num_values;
1444 if (pinfo) {
1445 *pinfo = talloc_move(p->mem_ctx, &info);
1448 done:
1449 if (winreg_pipe != NULL) {
1450 if (is_valid_policy_hnd(&key_hnd)) {
1451 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1453 if (is_valid_policy_hnd(&hive_hnd)) {
1454 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1458 TALLOC_FREE(enum_values);
1459 TALLOC_FREE(tmp_ctx);
1460 return result;
1463 WERROR winreg_printer_deleteform1(struct pipes_struct *p,
1464 const char *form_name)
1466 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1467 struct rpc_pipe_client *winreg_pipe = NULL;
1468 struct policy_handle hive_hnd, key_hnd;
1469 struct winreg_String wvalue;
1470 uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
1471 uint32_t i;
1472 WERROR result = WERR_OK;
1473 NTSTATUS status;
1474 TALLOC_CTX *tmp_ctx;
1476 for (i = 0; i < num_builtin; i++) {
1477 if (strequal(builtin_forms1[i].form_name, form_name)) {
1478 return WERR_INVALID_PARAMETER;
1482 tmp_ctx = talloc_new(p->mem_ctx);
1483 if (tmp_ctx == NULL) {
1484 return WERR_NOMEM;
1487 ZERO_STRUCT(hive_hnd);
1488 ZERO_STRUCT(key_hnd);
1490 result = winreg_printer_openkey(tmp_ctx,
1491 p->server_info,
1492 &winreg_pipe,
1493 TOP_LEVEL_CONTROL_FORMS_KEY,
1495 false,
1496 access_mask,
1497 &hive_hnd,
1498 &key_hnd);
1499 if (!W_ERROR_IS_OK(result)) {
1500 DEBUG(0, ("winreg_printer_deleteform1: Could not open key %s: %s\n",
1501 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
1502 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1503 result = WERR_INVALID_FORM_NAME;
1505 goto done;
1508 wvalue.name = form_name;
1509 status = rpccli_winreg_DeleteValue(winreg_pipe,
1510 tmp_ctx,
1511 &key_hnd,
1512 wvalue,
1513 &result);
1514 if (!NT_STATUS_IS_OK(status)) {
1515 DEBUG(0, ("winreg_printer_delteform1: Could not delete value %s: %s\n",
1516 wvalue.name, nt_errstr(status)));
1517 if (!W_ERROR_IS_OK(result)) {
1518 goto done;
1520 result = ntstatus_to_werror(status);
1521 goto done;
1524 result = WERR_OK;
1525 done:
1526 if (winreg_pipe != NULL) {
1527 if (is_valid_policy_hnd(&key_hnd)) {
1528 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1530 if (is_valid_policy_hnd(&hive_hnd)) {
1531 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1535 TALLOC_FREE(tmp_ctx);
1536 return result;
1539 WERROR winreg_printer_setform1(struct pipes_struct *p,
1540 const char *form_name,
1541 struct spoolss_AddFormInfo1 *form)
1543 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1544 struct rpc_pipe_client *winreg_pipe = NULL;
1545 struct policy_handle hive_hnd, key_hnd;
1546 struct winreg_String wvalue;
1547 DATA_BLOB blob;
1548 uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
1549 uint32_t i;
1550 WERROR result;
1551 NTSTATUS status;
1552 TALLOC_CTX *tmp_ctx;
1554 for (i = 0; i < num_builtin; i++) {
1555 if (strequal(builtin_forms1[i].form_name, form->form_name)) {
1556 result = WERR_INVALID_PARAM;
1557 goto done;
1561 tmp_ctx = talloc_new(p->mem_ctx);
1562 if (tmp_ctx == NULL) {
1563 return WERR_NOMEM;
1566 ZERO_STRUCT(hive_hnd);
1567 ZERO_STRUCT(key_hnd);
1569 result = winreg_printer_openkey(tmp_ctx,
1570 p->server_info,
1571 &winreg_pipe,
1572 TOP_LEVEL_CONTROL_FORMS_KEY,
1574 true,
1575 access_mask,
1576 &hive_hnd,
1577 &key_hnd);
1578 if (!W_ERROR_IS_OK(result)) {
1579 DEBUG(0, ("winreg_printer_setform1: Could not open key %s: %s\n",
1580 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
1581 goto done;
1584 /* If form_name != form->form_name then we renamed the form */
1585 if (strequal(form_name, form->form_name)) {
1586 result = winreg_printer_deleteform1(p, form_name);
1587 if (!W_ERROR_IS_OK(result)) {
1588 DEBUG(0, ("winreg_printer_setform1: Could not open key %s: %s\n",
1589 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
1590 goto done;
1594 wvalue.name = form->form_name;
1596 blob = data_blob_talloc(tmp_ctx, NULL, 32);
1597 SIVAL(blob.data, 0, form->size.width);
1598 SIVAL(blob.data, 4, form->size.height);
1599 SIVAL(blob.data, 8, form->area.left);
1600 SIVAL(blob.data, 12, form->area.top);
1601 SIVAL(blob.data, 16, form->area.right);
1602 SIVAL(blob.data, 20, form->area.bottom);
1603 SIVAL(blob.data, 24, 42);
1604 SIVAL(blob.data, 28, form->flags);
1606 status = rpccli_winreg_SetValue(winreg_pipe,
1607 tmp_ctx,
1608 &key_hnd,
1609 wvalue,
1610 REG_BINARY,
1611 blob.data,
1612 blob.length,
1613 &result);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 DEBUG(0, ("winreg_printer_setform1: Could not set value %s: %s\n",
1616 wvalue.name, nt_errstr(status)));
1617 if (!W_ERROR_IS_OK(result)) {
1618 goto done;
1620 result = ntstatus_to_werror(status);
1621 goto done;
1624 result = WERR_OK;
1625 done:
1626 if (winreg_pipe != NULL) {
1627 if (is_valid_policy_hnd(&key_hnd)) {
1628 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1630 if (is_valid_policy_hnd(&hive_hnd)) {
1631 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1635 TALLOC_FREE(tmp_ctx);
1636 return result;
1639 WERROR winreg_printer_getform1(struct pipes_struct *p,
1640 const char *form_name,
1641 struct spoolss_FormInfo1 *r)
1643 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1644 struct rpc_pipe_client *winreg_pipe = NULL;
1645 struct policy_handle hive_hnd, key_hnd;
1646 struct winreg_String wvalue;
1647 enum winreg_Type type_in;
1648 uint8_t *data_in;
1649 uint32_t data_in_size = 0;
1650 uint32_t value_len = 0;
1651 uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
1652 uint32_t i;
1653 WERROR result;
1654 NTSTATUS status;
1655 TALLOC_CTX *tmp_ctx;
1657 /* check builtin forms first */
1658 for (i = 0; i < num_builtin; i++) {
1659 if (strequal(builtin_forms1[i].form_name, form_name)) {
1660 *r = builtin_forms1[i];
1661 return WERR_OK;
1665 tmp_ctx = talloc_new(p->mem_ctx);
1666 if (tmp_ctx == NULL) {
1667 return WERR_NOMEM;
1670 ZERO_STRUCT(hive_hnd);
1671 ZERO_STRUCT(key_hnd);
1673 result = winreg_printer_openkey(tmp_ctx,
1674 p->server_info,
1675 &winreg_pipe,
1676 TOP_LEVEL_CONTROL_FORMS_KEY,
1678 true,
1679 access_mask,
1680 &hive_hnd,
1681 &key_hnd);
1682 if (!W_ERROR_IS_OK(result)) {
1683 DEBUG(0, ("winreg_printer_getform1: Could not open key %s: %s\n",
1684 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
1685 goto done;
1688 wvalue.name = form_name;
1691 * call QueryValue once with data == NULL to get the
1692 * needed memory size to be allocated, then allocate
1693 * data buffer and call again.
1695 status = rpccli_winreg_QueryValue(winreg_pipe,
1696 tmp_ctx,
1697 &key_hnd,
1698 &wvalue,
1699 &type_in,
1700 NULL,
1701 &data_in_size,
1702 &value_len,
1703 &result);
1704 if (!NT_STATUS_IS_OK(status)) {
1705 DEBUG(0, ("winreg_printer_getform1: Could not query value %s: %s\n",
1706 wvalue.name, nt_errstr(status)));
1707 if (!W_ERROR_IS_OK(result)) {
1708 goto done;
1710 result = ntstatus_to_werror(status);
1711 goto done;
1714 data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
1715 if (data_in == NULL) {
1716 result = WERR_NOMEM;
1717 goto done;
1719 value_len = 0;
1721 status = rpccli_winreg_QueryValue(winreg_pipe,
1722 tmp_ctx,
1723 &key_hnd,
1724 &wvalue,
1725 &type_in,
1726 data_in,
1727 &data_in_size,
1728 &value_len,
1729 &result);
1730 if (!NT_STATUS_IS_OK(status)) {
1731 DEBUG(0, ("winreg_printer_getform1: Could not query value %s: %s\n",
1732 wvalue.name, nt_errstr(status)));
1733 if (!W_ERROR_IS_OK(result)) {
1734 goto done;
1736 result = ntstatus_to_werror(status);
1737 goto done;
1740 r->form_name = talloc_strdup(p->mem_ctx, form_name);
1741 if (r->form_name == NULL) {
1742 result = WERR_NOMEM;
1743 goto done;
1746 r->size.width = IVAL(data_in, 0);
1747 r->size.height = IVAL(data_in, 4);
1748 r->area.left = IVAL(data_in, 8);
1749 r->area.top = IVAL(data_in, 12);
1750 r->area.right = IVAL(data_in, 16);
1751 r->area.bottom = IVAL(data_in, 20);
1752 /* skip index IVAL(data_in, 24)));*/
1753 r->flags = IVAL(data_in, 28);
1755 result = WERR_OK;
1756 done:
1757 if (winreg_pipe != NULL) {
1758 if (is_valid_policy_hnd(&key_hnd)) {
1759 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1761 if (is_valid_policy_hnd(&hive_hnd)) {
1762 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1766 TALLOC_FREE(tmp_ctx);
1767 return result;