s3-spoolss: Fix some valgrind warnings.
[Samba.git] / source3 / rpc_server / spoolss / srv_spoolss_util.c
blob9c41ac3dfb895983055dedcdbe186a8ea2d39a7c
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 "nt_printing.h"
24 #include "srv_spoolss_util.h"
25 #include "../librpc/gen_ndr/ndr_spoolss.h"
26 #include "../librpc/gen_ndr/ndr_winreg_c.h"
27 #include "../librpc/gen_ndr/ndr_security.h"
28 #include "secrets.h"
29 #include "rpc_server/rpc_ncacn_np.h"
30 #include "../libcli/security/security.h"
31 #include "rpc_client/cli_winreg.h"
32 #include "../libcli/registry/util_reg.h"
34 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
35 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
36 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
37 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
39 #define EMPTY_STRING ""
41 #define FILL_STRING(mem_ctx, in, out) \
42 do { \
43 if (in && strlen(in)) { \
44 out = talloc_strdup(mem_ctx, in); \
45 } else { \
46 out = talloc_strdup(mem_ctx, ""); \
47 } \
48 W_ERROR_HAVE_NO_MEMORY(out); \
49 } while (0);
51 #define CHECK_ERROR(result) \
52 if (W_ERROR_IS_OK(result)) continue; \
53 if (W_ERROR_EQUAL(result, WERR_NOT_FOUND)) result = WERR_OK; \
54 if (!W_ERROR_IS_OK(result)) break
56 /* FLAGS, NAME, with, height, left, top, right, bottom */
57 static const struct spoolss_FormInfo1 builtin_forms1[] = {
58 { SPOOLSS_FORM_BUILTIN, "10x11", {0x3e030,0x44368}, {0x0,0x0,0x3e030,0x44368} },
59 { SPOOLSS_FORM_BUILTIN, "10x14", {0x3e030,0x56d10}, {0x0,0x0,0x3e030,0x56d10} },
60 { SPOOLSS_FORM_BUILTIN, "11x17", {0x44368,0x696b8}, {0x0,0x0,0x44368,0x696b8} },
61 { SPOOLSS_FORM_BUILTIN, "12x11", {0x4a724,0x443e1}, {0x0,0x0,0x4a724,0x443e1} },
62 { SPOOLSS_FORM_BUILTIN, "15x11", {0x5d048,0x44368}, {0x0,0x0,0x5d048,0x44368} },
63 { SPOOLSS_FORM_BUILTIN, "6 3/4 Envelope", {0x167ab,0x284ec}, {0x0,0x0,0x167ab,0x284ec} },
64 { SPOOLSS_FORM_BUILTIN, "9x11", {0x37cf8,0x44368}, {0x0,0x0,0x37cf8,0x44368} },
65 { SPOOLSS_FORM_BUILTIN, "A0", {0xcd528,0x122488},{0x0,0x0,0xcd528,0x122488} },
66 { SPOOLSS_FORM_BUILTIN, "A1", {0x91050,0xcd528}, {0x0,0x0,0x91050,0xcd528} },
67 { SPOOLSS_FORM_BUILTIN, "A2", {0x668a0,0x91050}, {0x0,0x0,0x668a0,0x91050} },
68 { SPOOLSS_FORM_BUILTIN, "A3 Extra Transverse", {0x4e9d0,0x6ca48}, {0x0,0x0,0x4e9d0,0x6ca48} },
69 { SPOOLSS_FORM_BUILTIN, "A3 Extra", {0x4e9d0,0x6ca48}, {0x0,0x0,0x4e9d0,0x6ca48} },
70 { SPOOLSS_FORM_BUILTIN, "A3 Rotated", {0x668a0,0x48828}, {0x0,0x0,0x668a0,0x48828} },
71 { SPOOLSS_FORM_BUILTIN, "A3 Transverse", {0x48828,0x668a0}, {0x0,0x0,0x48828,0x668a0} },
72 { SPOOLSS_FORM_BUILTIN, "A3", {0x48828,0x668a0}, {0x0,0x0,0x48828,0x668a0} },
73 { SPOOLSS_FORM_BUILTIN, "A4 Extra", {0x397c2,0x4eb16}, {0x0,0x0,0x397c2,0x4eb16} },
74 { SPOOLSS_FORM_BUILTIN, "A4 Plus", {0x33450,0x50910}, {0x0,0x0,0x33450,0x50910} },
75 { SPOOLSS_FORM_BUILTIN, "A4 Rotated", {0x48828,0x33450}, {0x0,0x0,0x48828,0x33450} },
76 { SPOOLSS_FORM_BUILTIN, "A4 Small", {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
77 { SPOOLSS_FORM_BUILTIN, "A4 Transverse", {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
78 { SPOOLSS_FORM_BUILTIN, "A4", {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
79 { SPOOLSS_FORM_BUILTIN, "A5 Extra", {0x2a7b0,0x395f8}, {0x0,0x0,0x2a7b0,0x395f8} },
80 { SPOOLSS_FORM_BUILTIN, "A5 Rotated", {0x33450,0x24220}, {0x0,0x0,0x33450,0x24220} },
81 { SPOOLSS_FORM_BUILTIN, "A5 Transverse", {0x24220,0x33450}, {0x0,0x0,0x24220,0x33450} },
82 { SPOOLSS_FORM_BUILTIN, "A5", {0x24220,0x33450}, {0x0,0x0,0x24220,0x33450} },
83 { SPOOLSS_FORM_BUILTIN, "A6 Rotated", {0x24220,0x19a28}, {0x0,0x0,0x24220,0x19a28} },
84 { SPOOLSS_FORM_BUILTIN, "A6", {0x19a28,0x24220}, {0x0,0x0,0x19a28,0x24220} },
85 { SPOOLSS_FORM_BUILTIN, "B4 (ISO)", {0x3d090,0x562e8}, {0x0,0x0,0x3d090,0x562e8} },
86 { SPOOLSS_FORM_BUILTIN, "B4 (JIS) Rotated", {0x58de0,0x3ebe8}, {0x0,0x0,0x58de0,0x3ebe8} },
87 { SPOOLSS_FORM_BUILTIN, "B4 (JIS)", {0x3ebe8,0x58de0}, {0x0,0x0,0x3ebe8,0x58de0} },
88 { SPOOLSS_FORM_BUILTIN, "B5 (ISO) Extra", {0x31128,0x43620}, {0x0,0x0,0x31128,0x43620} },
89 { SPOOLSS_FORM_BUILTIN, "B5 (JIS) Rotated", {0x3ebe8,0x2c6f0}, {0x0,0x0,0x3ebe8,0x2c6f0} },
90 { SPOOLSS_FORM_BUILTIN, "B5 (JIS) Transverse", {0x2c6f0,0x3ebe8}, {0x0,0x0,0x2c6f0,0x3ebe8} },
91 { SPOOLSS_FORM_BUILTIN, "B5 (JIS)", {0x2c6f0,0x3ebe8}, {0x0,0x0,0x2c6f0,0x3ebe8} },
92 { SPOOLSS_FORM_BUILTIN, "B6 (JIS) Rotated", {0x2c6f0,0x1f400}, {0x0,0x0,0x2c6f0,0x1f400} },
93 { SPOOLSS_FORM_BUILTIN, "B6 (JIS)", {0x1f400,0x2c6f0}, {0x0,0x0,0x1f400,0x2c6f0} },
94 { SPOOLSS_FORM_BUILTIN, "C size sheet", {0x696b8,0x886d0}, {0x0,0x0,0x696b8,0x886d0} },
95 { SPOOLSS_FORM_BUILTIN, "D size sheet", {0x886d0,0xd2d70}, {0x0,0x0,0x886d0,0xd2d70} },
96 { SPOOLSS_FORM_BUILTIN, "Double Japan Postcard Rotated", {0x24220,0x30d40}, {0x0,0x0,0x24220,0x30d40} },
97 { SPOOLSS_FORM_BUILTIN, "E size sheet", {0xd2d70,0x110da0},{0x0,0x0,0xd2d70,0x110da0} },
98 { SPOOLSS_FORM_BUILTIN, "Envelope #10", {0x19947,0x3ae94}, {0x0,0x0,0x19947,0x3ae94} },
99 { SPOOLSS_FORM_BUILTIN, "Envelope #11", {0x1be7c,0x40565}, {0x0,0x0,0x1be7c,0x40565} },
100 { SPOOLSS_FORM_BUILTIN, "Envelope #12", {0x1d74a,0x44368}, {0x0,0x0,0x1d74a,0x44368} },
101 { SPOOLSS_FORM_BUILTIN, "Envelope #14", {0x1f018,0x47504}, {0x0,0x0,0x1f018,0x47504} },
102 { SPOOLSS_FORM_BUILTIN, "Envelope #9", {0x18079,0x37091}, {0x0,0x0,0x18079,0x37091} },
103 { SPOOLSS_FORM_BUILTIN, "Envelope B4", {0x3d090,0x562e8}, {0x0,0x0,0x3d090,0x562e8} },
104 { SPOOLSS_FORM_BUILTIN, "Envelope B5", {0x2af80,0x3d090}, {0x0,0x0,0x2af80,0x3d090} },
105 { SPOOLSS_FORM_BUILTIN, "Envelope B6", {0x2af80,0x1e848}, {0x0,0x0,0x2af80,0x1e848} },
106 { SPOOLSS_FORM_BUILTIN, "Envelope C3", {0x4f1a0,0x6fd10}, {0x0,0x0,0x4f1a0,0x6fd10} },
107 { SPOOLSS_FORM_BUILTIN, "Envelope C4", {0x37e88,0x4f1a0}, {0x0,0x0,0x37e88,0x4f1a0} },
108 { SPOOLSS_FORM_BUILTIN, "Envelope C5", {0x278d0,0x37e88}, {0x0,0x0,0x278d0,0x37e88} },
109 { SPOOLSS_FORM_BUILTIN, "Envelope C6", {0x1bd50,0x278d0}, {0x0,0x0,0x1bd50,0x278d0} },
110 { SPOOLSS_FORM_BUILTIN, "Envelope C65", {0x1bd50,0x37e88}, {0x0,0x0,0x1bd50,0x37e88} },
111 { SPOOLSS_FORM_BUILTIN, "Envelope DL", {0x1adb0,0x35b60}, {0x0,0x0,0x1adb0,0x35b60} },
112 { SPOOLSS_FORM_BUILTIN, "Envelope Invite", {0x35b60,0x35b60}, {0x0,0x0,0x35b60,0x35b60} },
113 { SPOOLSS_FORM_BUILTIN, "Envelope Monarch", {0x18079,0x2e824}, {0x0,0x0,0x18079,0x2e824} },
114 { SPOOLSS_FORM_BUILTIN, "Envelope", {0x1adb0,0x38270}, {0x0,0x0,0x1adb0,0x38270} },
115 { SPOOLSS_FORM_BUILTIN, "Executive", {0x2cf56,0x411cc}, {0x0,0x0,0x2cf56,0x411cc} },
116 { SPOOLSS_FORM_BUILTIN, "Folio", {0x34b5c,0x509d8}, {0x0,0x0,0x34b5c,0x509d8} },
117 { SPOOLSS_FORM_BUILTIN, "German Legal Fanfold", {0x34b5c,0x509d8}, {0x0,0x0,0x34b5c,0x509d8} },
118 { SPOOLSS_FORM_BUILTIN, "German Std Fanfold", {0x34b5c,0x4a6a0}, {0x0,0x0,0x34b5c,0x4a6a0} },
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, "Japan Envelope Kaku #2 Rotated", {0x510e0,0x3a980}, {0x0,0x0,0x510e0,0x3a980} },
122 { SPOOLSS_FORM_BUILTIN, "Japan Envelope Kaku #3 Rotated", {0x43a08,0x34bc0}, {0x0,0x0,0x43a08,0x34bc0} },
123 { SPOOLSS_FORM_BUILTIN, "Japan Envelope You #4 Rotated", {0x395f8,0x19a28}, {0x0,0x0,0x395f8,0x19a28} },
124 { SPOOLSS_FORM_BUILTIN, "Japan Envelope You #4", {0x19a28,0x395f8}, {0x0,0x0,0x19a28,0x395f8} },
125 { SPOOLSS_FORM_BUILTIN, "Japanese Double Postcard", {0x30d40,0x24220}, {0x0,0x0,0x30d40,0x24220} },
126 { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Chou #3", {0x1d4c0,0x395f8}, {0x0,0x0,0x1d4c0,0x395f8} },
127 { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Chou #4", {0x15f90,0x320c8}, {0x0,0x0,0x15f90,0x320c8} },
128 { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Kaku #2", {0x3a980,0x510e0}, {0x0,0x0,0x3a980,0x510e0} },
129 { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Kaku #3", {0x34bc0,0x43a08}, {0x0,0x0,0x34bc0,0x43a08} },
130 { SPOOLSS_FORM_BUILTIN, "Japanese Postcard Rotated", {0x24220,0x186a0}, {0x0,0x0,0x24220,0x186a0} },
131 { SPOOLSS_FORM_BUILTIN, "Japanese Postcard", {0x186a0,0x24220}, {0x0,0x0,0x186a0,0x24220} },
132 { SPOOLSS_FORM_BUILTIN, "Ledger", {0x696b8,0x44368}, {0x0,0x0,0x696b8,0x44368} },
133 { SPOOLSS_FORM_BUILTIN, "Legal Extra", {0x3ae94,0x5d048}, {0x0,0x0,0x3ae94,0x5d048} },
134 { SPOOLSS_FORM_BUILTIN, "Legal", {0x34b5c,0x56d10}, {0x0,0x0,0x34b5c,0x56d10} },
135 { SPOOLSS_FORM_BUILTIN, "Letter Extra Transverse", {0x3ae94,0x4a6a0}, {0x0,0x0,0x3ae94,0x4a6a0} },
136 { SPOOLSS_FORM_BUILTIN, "Letter Extra", {0x3ae94,0x4a6a0}, {0x0,0x0,0x3ae94,0x4a6a0} },
137 { SPOOLSS_FORM_BUILTIN, "Letter Plus", {0x34b5c,0x4eb16}, {0x0,0x0,0x34b5c,0x4eb16} },
138 { SPOOLSS_FORM_BUILTIN, "Letter Rotated", {0x44368,0x34b5c}, {0x0,0x0,0x44368,0x34b5c} },
139 { SPOOLSS_FORM_BUILTIN, "Letter Small", {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
140 { SPOOLSS_FORM_BUILTIN, "Letter Transverse", {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
141 { SPOOLSS_FORM_BUILTIN, "Letter", {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
142 { SPOOLSS_FORM_BUILTIN, "Note", {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
143 { SPOOLSS_FORM_BUILTIN, "PRC 16K Rotated", {0x3f7a0,0x2de60}, {0x0,0x0,0x3f7a0,0x2de60} },
144 { SPOOLSS_FORM_BUILTIN, "PRC 16K", {0x2de60,0x3f7a0}, {0x0,0x0,0x2de60,0x3f7a0} },
145 { SPOOLSS_FORM_BUILTIN, "PRC 32K Rotated", {0x2cec0,0x1fbd0}, {0x0,0x0,0x2cec0,0x1fbd0} },
146 { SPOOLSS_FORM_BUILTIN, "PRC 32K", {0x1fbd0,0x2cec0}, {0x0,0x0,0x1fbd0,0x2cec0} },
147 { SPOOLSS_FORM_BUILTIN, "PRC 32K(Big) Rotated", {0x318f8,0x222e0}, {0x0,0x0,0x318f8,0x222e0} },
148 { SPOOLSS_FORM_BUILTIN, "PRC 32K(Big)", {0x222e0,0x318f8}, {0x0,0x0,0x222e0,0x318f8} },
149 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #1 Rotated", {0x28488,0x18e70}, {0x0,0x0,0x28488,0x18e70} },
150 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #1", {0x18e70,0x28488}, {0x0,0x0,0x18e70,0x28488} },
151 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #10 Rotated", {0x6fd10,0x4f1a0}, {0x0,0x0,0x6fd10,0x4f1a0} },
152 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #10", {0x4f1a0,0x6fd10}, {0x0,0x0,0x4f1a0,0x6fd10} },
153 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #2 Rotated", {0x2af80,0x18e70}, {0x0,0x0,0x2af80,0x18e70} },
154 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #2", {0x18e70,0x2af80}, {0x0,0x0,0x18e70,0x2af80} },
155 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #3 Rotated", {0x2af80,0x1e848}, {0x0,0x0,0x2af80,0x1e848} },
156 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #3", {0x1e848,0x2af80}, {0x0,0x0,0x1e848,0x2af80} },
157 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #4 Rotated", {0x32c80,0x1adb0}, {0x0,0x0,0x32c80,0x1adb0} },
158 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #4", {0x1adb0,0x32c80}, {0x0,0x0,0x1adb0,0x32c80} },
159 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #5 Rotated", {0x35b60,0x1adb0}, {0x0,0x0,0x35b60,0x1adb0} },
160 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #5", {0x1adb0,0x35b60}, {0x0,0x0,0x1adb0,0x35b60} },
161 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #6 Rotated", {0x38270,0x1d4c0}, {0x0,0x0,0x38270,0x1d4c0} },
162 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #6", {0x1d4c0,0x38270}, {0x0,0x0,0x1d4c0,0x38270} },
163 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #7 Rotated", {0x38270,0x27100}, {0x0,0x0,0x38270,0x27100} },
164 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #7", {0x27100,0x38270}, {0x0,0x0,0x27100,0x38270} },
165 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #8 Rotated", {0x4b708,0x1d4c0}, {0x0,0x0,0x4b708,0x1d4c0} },
166 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #8", {0x1d4c0,0x4b708}, {0x0,0x0,0x1d4c0,0x4b708} },
167 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #9 Rotated", {0x4f1a0,0x37e88}, {0x0,0x0,0x4f1a0,0x37e88} },
168 { SPOOLSS_FORM_BUILTIN, "PRC Envelope #9", {0x37e88,0x4f1a0}, {0x0,0x0,0x37e88,0x4f1a0} },
169 { SPOOLSS_FORM_BUILTIN, "Quarto", {0x347d8,0x43238}, {0x0,0x0,0x347d8,0x43238} },
170 { SPOOLSS_FORM_BUILTIN, "Reserved48", {0x1,0x1}, {0x0,0x0,0x1,0x1} },
171 { SPOOLSS_FORM_BUILTIN, "Reserved49", {0x1,0x1}, {0x0,0x0,0x1,0x1} },
172 { SPOOLSS_FORM_BUILTIN, "Statement", {0x221b4,0x34b5c}, {0x0,0x0,0x221b4,0x34b5c} },
173 { SPOOLSS_FORM_BUILTIN, "Super A", {0x376b8,0x56ea0}, {0x0,0x0,0x376b8,0x56ea0} },
174 { SPOOLSS_FORM_BUILTIN, "Super B", {0x4a768,0x76e58}, {0x0,0x0,0x4a768,0x76e58} },
175 { SPOOLSS_FORM_BUILTIN, "Tabloid Extra", {0x4a6a0,0x6f9f0}, {0x0,0x0,0x4a6a0,0x6f9f0} },
176 { SPOOLSS_FORM_BUILTIN, "Tabloid", {0x44368,0x696b8}, {0x0,0x0,0x44368,0x696b8} },
177 { SPOOLSS_FORM_BUILTIN, "US Std Fanfold", {0x5c3e1,0x44368}, {0x0,0x0,0x5c3e1,0x44368} }
180 /********************************************************************
181 static helper functions
182 ********************************************************************/
184 /****************************************************************************
185 Update the changeid time.
186 ****************************************************************************/
188 * @internal
190 * @brief Update the ChangeID time of a printer.
192 * This is SO NASTY as some drivers need this to change, others need it
193 * static. This value will change every second, and I must hope that this
194 * is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
195 * UTAH ! JRA.
197 * @return The ChangeID.
199 static uint32_t winreg_printer_rev_changeid(void)
201 struct timeval tv;
203 get_process_uptime(&tv);
205 #if 1 /* JERRY */
206 /* Return changeid as msec since spooler restart */
207 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
208 #else
210 * This setting seems to work well but is too untested
211 * to replace the above calculation. Left in for experimentation
212 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
214 return tv.tv_sec * 10 + tv.tv_usec / 100000;
215 #endif
219 * @internal
221 * @brief Connect to the interal winreg server and open the given printer key.
223 * The function will create the needed subkeys if they don't exist.
225 * @param[in] mem_ctx The memory context to use.
227 * @param[in] session_info The supplied server info.
229 * @param[out] binding_handle A pointer for the winreg dcerpc binding handle.
231 * @param[in] path The path to the key to open.
233 * @param[in] key The key to open.
235 * @param[in] create_key Set to true if the key should be created if it
236 * doesn't exist.
238 * @param[in] access_mask The access mask to open the key.
240 * @param[out] hive_handle A policy handle for the opened hive.
242 * @param[out] key_handle A policy handle for the opened key.
244 * @return WERR_OK on success, the corresponding DOS error
245 * code if something gone wrong.
247 static WERROR winreg_printer_openkey(TALLOC_CTX *mem_ctx,
248 const struct auth_serversupplied_info *session_info,
249 struct messaging_context *msg_ctx,
250 struct dcerpc_binding_handle **winreg_binding_handle,
251 const char *path,
252 const char *key,
253 bool create_key,
254 uint32_t access_mask,
255 struct policy_handle *hive_handle,
256 struct policy_handle *key_handle)
258 static struct client_address client_id;
259 struct dcerpc_binding_handle *binding_handle;
260 struct winreg_String wkey, wkeyclass;
261 char *keyname;
262 NTSTATUS status;
263 WERROR result = WERR_OK;
265 strlcpy(client_id.addr, "127.0.0.1", sizeof(client_id.addr));
266 client_id.name = "127.0.0.1";
268 status = rpcint_binding_handle(mem_ctx,
269 &ndr_table_winreg,
270 &client_id,
271 session_info,
272 msg_ctx,
273 &binding_handle);
274 if (!NT_STATUS_IS_OK(status)) {
275 DEBUG(0, ("winreg_printer_openkey: Could not connect to winreg pipe: %s\n",
276 nt_errstr(status)));
277 return ntstatus_to_werror(status);
280 status = dcerpc_winreg_OpenHKLM(binding_handle,
281 mem_ctx,
282 NULL,
283 access_mask,
284 hive_handle,
285 &result);
286 if (!NT_STATUS_IS_OK(status)) {
287 DEBUG(0, ("winreg_printer_openkey: Could not open HKLM hive: %s\n",
288 nt_errstr(status)));
289 talloc_free(binding_handle);
290 return ntstatus_to_werror(status);
292 if (!W_ERROR_IS_OK(result)) {
293 DEBUG(0, ("winreg_printer_openkey: Could not open HKLM hive: %s\n",
294 win_errstr(result)));
295 talloc_free(binding_handle);
296 return result;
299 if (key && *key) {
300 keyname = talloc_asprintf(mem_ctx, "%s\\%s", path, key);
301 } else {
302 keyname = talloc_strdup(mem_ctx, path);
304 if (keyname == NULL) {
305 talloc_free(binding_handle);
306 return WERR_NOMEM;
309 ZERO_STRUCT(wkey);
310 wkey.name = keyname;
312 if (create_key) {
313 enum winreg_CreateAction action = REG_ACTION_NONE;
315 ZERO_STRUCT(wkeyclass);
316 wkeyclass.name = "";
318 status = dcerpc_winreg_CreateKey(binding_handle,
319 mem_ctx,
320 hive_handle,
321 wkey,
322 wkeyclass,
324 access_mask,
325 NULL,
326 key_handle,
327 &action,
328 &result);
329 switch (action) {
330 case REG_ACTION_NONE:
331 DEBUG(8, ("winreg_printer_openkey:createkey did nothing -- huh?\n"));
332 break;
333 case REG_CREATED_NEW_KEY:
334 DEBUG(8, ("winreg_printer_openkey: createkey created %s\n", keyname));
335 break;
336 case REG_OPENED_EXISTING_KEY:
337 DEBUG(8, ("winreg_printer_openkey: createkey opened existing %s\n", keyname));
338 break;
340 } else {
341 status = dcerpc_winreg_OpenKey(binding_handle,
342 mem_ctx,
343 hive_handle,
344 wkey,
346 access_mask,
347 key_handle,
348 &result);
350 if (!NT_STATUS_IS_OK(status)) {
351 talloc_free(binding_handle);
352 return ntstatus_to_werror(status);
354 if (!W_ERROR_IS_OK(result)) {
355 talloc_free(binding_handle);
356 return result;
359 *winreg_binding_handle = binding_handle;
361 return WERR_OK;
365 * @brief Create the registry keyname for the given printer.
367 * @param[in] mem_ctx The memory context to use.
369 * @param[in] printer The name of the printer to get the registry key.
371 * @return The registry key or NULL on error.
373 static char *winreg_printer_data_keyname(TALLOC_CTX *mem_ctx, const char *printer) {
374 return talloc_asprintf(mem_ctx, "%s\\%s", TOP_LEVEL_PRINT_PRINTERS_KEY, printer);
378 * @internal
380 * @brief Enumerate values of an opened key handle and retrieve the data.
382 * @param[in] mem_ctx The memory context to use.
384 * @param[in] winreg_handle The binding handle for the rpc connection.
386 * @param[in] key_hnd The opened key handle.
388 * @param[out] pnum_values A pointer to store he number of values found.
390 * @param[out] pnum_values A pointer to store the number of values we found.
392 * @return WERR_OK on success, the corresponding DOS error
393 * code if something gone wrong.
395 static WERROR winreg_printer_enumvalues(TALLOC_CTX *mem_ctx,
396 struct dcerpc_binding_handle *winreg_handle,
397 struct policy_handle *key_hnd,
398 uint32_t *pnum_values,
399 struct spoolss_PrinterEnumValues **penum_values)
401 TALLOC_CTX *tmp_ctx;
402 uint32_t num_subkeys, max_subkeylen, max_classlen;
403 uint32_t num_values, max_valnamelen, max_valbufsize;
404 uint32_t secdescsize;
405 uint32_t i;
406 NTTIME last_changed_time;
407 struct winreg_String classname;
409 struct spoolss_PrinterEnumValues *enum_values;
411 WERROR result = WERR_OK;
412 NTSTATUS status;
414 tmp_ctx = talloc_stackframe();
415 if (tmp_ctx == NULL) {
416 return WERR_NOMEM;
419 ZERO_STRUCT(classname);
421 status = dcerpc_winreg_QueryInfoKey(winreg_handle,
422 tmp_ctx,
423 key_hnd,
424 &classname,
425 &num_subkeys,
426 &max_subkeylen,
427 &max_classlen,
428 &num_values,
429 &max_valnamelen,
430 &max_valbufsize,
431 &secdescsize,
432 &last_changed_time,
433 &result);
434 if (!NT_STATUS_IS_OK(status)) {
435 DEBUG(0, ("winreg_printer_enumvalues: Could not query info: %s\n",
436 nt_errstr(status)));
437 result = ntstatus_to_werror(status);
438 goto error;
440 if (!W_ERROR_IS_OK(result)) {
441 DEBUG(0, ("winreg_printer_enumvalues: Could not query info: %s\n",
442 win_errstr(result)));
443 goto error;
446 if (num_values == 0) {
447 *pnum_values = 0;
448 TALLOC_FREE(tmp_ctx);
449 return WERR_OK;
452 enum_values = TALLOC_ARRAY(tmp_ctx, struct spoolss_PrinterEnumValues, num_values);
453 if (enum_values == NULL) {
454 result = WERR_NOMEM;
455 goto error;
458 for (i = 0; i < num_values; i++) {
459 struct spoolss_PrinterEnumValues val;
460 struct winreg_ValNameBuf name_buf;
461 enum winreg_Type type = REG_NONE;
462 uint8_t *data;
463 uint32_t data_size;
464 uint32_t length;
465 char n = '\0';
467 name_buf.name = &n;
468 name_buf.size = max_valnamelen + 2;
469 name_buf.length = 0;
471 data_size = max_valbufsize;
472 data = NULL;
473 if (data_size) {
474 data = (uint8_t *) talloc_zero_size(tmp_ctx, data_size);
476 length = 0;
478 status = dcerpc_winreg_EnumValue(winreg_handle,
479 tmp_ctx,
480 key_hnd,
482 &name_buf,
483 &type,
484 data,
485 data_size ? &data_size : NULL,
486 &length,
487 &result);
488 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
489 result = WERR_OK;
490 status = NT_STATUS_OK;
491 break;
494 if (!NT_STATUS_IS_OK(status)) {
495 DEBUG(0, ("winreg_printer_enumvalues: Could not enumerate values: %s\n",
496 nt_errstr(status)));
497 result = ntstatus_to_werror(status);
498 goto error;
500 if (!W_ERROR_IS_OK(result)) {
501 DEBUG(0, ("winreg_printer_enumvalues: Could not enumerate values: %s\n",
502 win_errstr(result)));
503 goto error;
506 if (name_buf.name == NULL) {
507 result = WERR_INVALID_PARAMETER;
508 goto error;
511 val.value_name = talloc_strdup(enum_values, name_buf.name);
512 if (val.value_name == NULL) {
513 result = WERR_NOMEM;
514 goto error;
516 val.value_name_len = strlen_m_term(val.value_name) * 2;
518 val.type = type;
519 val.data_length = length;
520 val.data = NULL;
521 if (val.data_length) {
522 val.data = talloc(enum_values, DATA_BLOB);
523 if (val.data == NULL) {
524 result = WERR_NOMEM;
525 goto error;
527 *val.data = data_blob_talloc(val.data, data, val.data_length);
530 enum_values[i] = val;
533 *pnum_values = num_values;
534 if (penum_values) {
535 *penum_values = talloc_move(mem_ctx, &enum_values);
538 result = WERR_OK;
540 error:
541 TALLOC_FREE(tmp_ctx);
542 return result;
546 * @internal
548 * @brief A function to delete a key and its subkeys recurively.
550 * @param[in] mem_ctx The memory context to use.
552 * @param[in] winreg_handle The binding handle for the rpc connection.
554 * @param[in] hive_handle A opened hive handle to the key.
556 * @param[in] access_mask The access mask to access the key.
558 * @param[in] key The key to delete
560 * @return WERR_OK on success, the corresponding DOS error
561 * code if something gone wrong.
563 static WERROR winreg_printer_delete_subkeys(TALLOC_CTX *mem_ctx,
564 struct dcerpc_binding_handle *winreg_handle,
565 struct policy_handle *hive_handle,
566 uint32_t access_mask,
567 const char *key)
569 const char **subkeys = NULL;
570 uint32_t num_subkeys = 0;
571 struct policy_handle key_hnd;
572 struct winreg_String wkey = { 0, };
573 WERROR result = WERR_OK;
574 NTSTATUS status;
575 uint32_t i;
577 ZERO_STRUCT(key_hnd);
578 wkey.name = key;
580 DEBUG(2, ("winreg_printer_delete_subkeys: delete key %s\n", key));
581 /* open the key */
582 status = dcerpc_winreg_OpenKey(winreg_handle,
583 mem_ctx,
584 hive_handle,
585 wkey,
587 access_mask,
588 &key_hnd,
589 &result);
590 if (!NT_STATUS_IS_OK(status)) {
591 DEBUG(0, ("winreg_printer_delete_subkeys: Could not open key %s: %s\n",
592 wkey.name, nt_errstr(status)));
593 return ntstatus_to_werror(status);
595 if (!W_ERROR_IS_OK(result)) {
596 DEBUG(0, ("winreg_printer_delete_subkeys: Could not open key %s: %s\n",
597 wkey.name, win_errstr(result)));
598 return result;
601 status = dcerpc_winreg_enum_keys(mem_ctx,
602 winreg_handle,
603 &key_hnd,
604 &num_subkeys,
605 &subkeys,
606 &result);
607 if (!NT_STATUS_IS_OK(status)) {
608 result = ntstatus_to_werror(status);
610 if (!W_ERROR_IS_OK(result)) {
611 goto done;
614 for (i = 0; i < num_subkeys; i++) {
615 /* create key + subkey */
616 char *subkey = talloc_asprintf(mem_ctx, "%s\\%s", key, subkeys[i]);
617 if (subkey == NULL) {
618 goto done;
621 DEBUG(2, ("winreg_printer_delete_subkeys: delete subkey %s\n", subkey));
622 result = winreg_printer_delete_subkeys(mem_ctx,
623 winreg_handle,
624 hive_handle,
625 access_mask,
626 subkey);
627 if (!W_ERROR_IS_OK(result)) {
628 goto done;
632 if (is_valid_policy_hnd(&key_hnd)) {
633 WERROR ignore;
634 dcerpc_winreg_CloseKey(winreg_handle, mem_ctx, &key_hnd, &ignore);
637 wkey.name = key;
639 status = dcerpc_winreg_DeleteKey(winreg_handle,
640 mem_ctx,
641 hive_handle,
642 wkey,
643 &result);
644 if (!NT_STATUS_IS_OK(status)) {
645 result = ntstatus_to_werror(status);
648 done:
649 if (is_valid_policy_hnd(&key_hnd)) {
650 WERROR ignore;
652 dcerpc_winreg_CloseKey(winreg_handle, mem_ctx, &key_hnd, &ignore);
655 return result;
658 static WERROR winreg_printer_opendriver(TALLOC_CTX *mem_ctx,
659 const struct auth_serversupplied_info *session_info,
660 struct messaging_context *msg_ctx,
661 const char *drivername,
662 const char *architecture,
663 uint32_t version,
664 uint32_t access_mask,
665 bool create,
666 struct dcerpc_binding_handle **winreg_binding_handle,
667 struct policy_handle *hive_hnd,
668 struct policy_handle *key_hnd)
670 WERROR result;
671 char *key_name;
673 key_name = talloc_asprintf(mem_ctx, "%s\\Environments\\%s\\Drivers\\Version-%u",
674 TOP_LEVEL_CONTROL_KEY,
675 architecture, version);
676 if (!key_name) {
677 return WERR_NOMEM;
680 result = winreg_printer_openkey(mem_ctx,
681 session_info,
682 msg_ctx,
683 winreg_binding_handle,
684 key_name,
685 drivername,
686 create,
687 access_mask,
688 hive_hnd,
689 key_hnd);
690 return result;
693 static WERROR winreg_enumval_to_dword(TALLOC_CTX *mem_ctx,
694 struct spoolss_PrinterEnumValues *v,
695 const char *valuename, uint32_t *dw)
697 /* just return if it is not the one we are looking for */
698 if (strcmp(valuename, v->value_name) != 0) {
699 return WERR_NOT_FOUND;
702 if (v->type != REG_DWORD) {
703 return WERR_INVALID_DATATYPE;
706 if (v->data_length != 4) {
707 *dw = 0;
708 return WERR_OK;
711 *dw = IVAL(v->data->data, 0);
712 return WERR_OK;
715 static WERROR winreg_enumval_to_sz(TALLOC_CTX *mem_ctx,
716 struct spoolss_PrinterEnumValues *v,
717 const char *valuename, const char **_str)
719 /* just return if it is not the one we are looking for */
720 if (strcmp(valuename, v->value_name) != 0) {
721 return WERR_NOT_FOUND;
724 if (v->type != REG_SZ) {
725 return WERR_INVALID_DATATYPE;
728 if (v->data_length == 0) {
729 *_str = talloc_strdup(mem_ctx, EMPTY_STRING);
730 if (*_str == NULL) {
731 return WERR_NOMEM;
733 return WERR_OK;
736 if (!pull_reg_sz(mem_ctx, v->data, _str)) {
737 return WERR_NOMEM;
740 return WERR_OK;
743 static WERROR winreg_enumval_to_multi_sz(TALLOC_CTX *mem_ctx,
744 struct spoolss_PrinterEnumValues *v,
745 const char *valuename,
746 const char ***array)
748 /* just return if it is not the one we are looking for */
749 if (strcmp(valuename, v->value_name) != 0) {
750 return WERR_NOT_FOUND;
753 if (v->type != REG_MULTI_SZ) {
754 return WERR_INVALID_DATATYPE;
757 if (v->data_length == 0) {
758 *array = talloc_array(mem_ctx, const char *, 1);
759 if (*array == NULL) {
760 return WERR_NOMEM;
762 *array[0] = NULL;
763 return WERR_OK;
766 if (!pull_reg_multi_sz(mem_ctx, v->data, array)) {
767 return WERR_NOMEM;
770 return WERR_OK;
773 static WERROR winreg_printer_write_date(TALLOC_CTX *mem_ctx,
774 struct dcerpc_binding_handle *winreg_handle,
775 struct policy_handle *key_handle,
776 const char *value,
777 NTTIME data)
779 struct winreg_String wvalue = { 0, };
780 DATA_BLOB blob;
781 WERROR result = WERR_OK;
782 NTSTATUS status;
783 const char *str;
784 struct tm *tm;
785 time_t t;
787 if (data == 0) {
788 str = talloc_strdup(mem_ctx, "01/01/1601");
789 } else {
790 t = nt_time_to_unix(data);
791 tm = localtime(&t);
792 if (tm == NULL) {
793 return map_werror_from_unix(errno);
795 str = talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
796 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
798 if (!str) {
799 return WERR_NOMEM;
802 wvalue.name = value;
803 if (!push_reg_sz(mem_ctx, &blob, str)) {
804 return WERR_NOMEM;
806 status = dcerpc_winreg_SetValue(winreg_handle,
807 mem_ctx,
808 key_handle,
809 wvalue,
810 REG_SZ,
811 blob.data,
812 blob.length,
813 &result);
814 if (!NT_STATUS_IS_OK(status)) {
815 result = ntstatus_to_werror(status);
817 if (!W_ERROR_IS_OK(result)) {
818 DEBUG(0, ("winreg_printer_write_date: Could not set value %s: %s\n",
819 wvalue.name, win_errstr(result)));
822 return result;
825 static WERROR winreg_printer_date_to_NTTIME(const char *str, NTTIME *data)
827 struct tm tm;
828 time_t t;
830 if (strequal(str, "01/01/1601")) {
831 *data = 0;
832 return WERR_OK;
835 ZERO_STRUCT(tm);
837 if (sscanf(str, "%d/%d/%d",
838 &tm.tm_mon, &tm.tm_mday, &tm.tm_year) != 3) {
839 return WERR_INVALID_PARAMETER;
841 tm.tm_mon -= 1;
842 tm.tm_year -= 1900;
843 tm.tm_isdst = -1;
845 t = mktime(&tm);
846 unix_to_nt_time(data, t);
848 return WERR_OK;
851 static WERROR winreg_printer_write_ver(TALLOC_CTX *mem_ctx,
852 struct dcerpc_binding_handle *winreg_handle,
853 struct policy_handle *key_handle,
854 const char *value,
855 uint64_t data)
857 struct winreg_String wvalue = { 0, };
858 DATA_BLOB blob;
859 WERROR result = WERR_OK;
860 NTSTATUS status;
861 char *str;
863 /* FIXME: check format is right,
864 * this needs to be something like: 6.1.7600.16385 */
865 str = talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
866 (unsigned)((data >> 48) & 0xFFFF),
867 (unsigned)((data >> 32) & 0xFFFF),
868 (unsigned)((data >> 16) & 0xFFFF),
869 (unsigned)(data & 0xFFFF));
870 if (!str) {
871 return WERR_NOMEM;
874 wvalue.name = value;
875 if (!push_reg_sz(mem_ctx, &blob, str)) {
876 return WERR_NOMEM;
878 status = dcerpc_winreg_SetValue(winreg_handle,
879 mem_ctx,
880 key_handle,
881 wvalue,
882 REG_SZ,
883 blob.data,
884 blob.length,
885 &result);
886 if (!NT_STATUS_IS_OK(status)) {
887 result = ntstatus_to_werror(status);
889 if (!W_ERROR_IS_OK(result)) {
890 DEBUG(0, ("winreg_printer_write_date: Could not set value %s: %s\n",
891 wvalue.name, win_errstr(result)));
894 return result;
897 static WERROR winreg_printer_ver_to_dword(const char *str, uint64_t *data)
899 unsigned int v1, v2, v3, v4;
901 if (sscanf(str, "%u.%u.%u.%u", &v1, &v2, &v3, &v4) != 4) {
902 return WERR_INVALID_PARAMETER;
905 *data = ((uint64_t)(v1 & 0xFFFF) << 48) +
906 ((uint64_t)(v2 & 0xFFFF) << 32) +
907 ((uint64_t)(v3 & 0xFFFF) << 16) +
908 (uint64_t)(v2 & 0xFFFF);
910 return WERR_OK;
913 /********************************************************************
914 Public winreg function for spoolss
915 ********************************************************************/
917 WERROR winreg_create_printer(TALLOC_CTX *mem_ctx,
918 const struct auth_serversupplied_info *session_info,
919 struct messaging_context *msg_ctx,
920 const char *sharename)
922 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
923 struct dcerpc_binding_handle *winreg_handle = NULL;
924 struct policy_handle hive_hnd, key_hnd;
925 struct spoolss_SetPrinterInfo2 *info2;
926 struct security_descriptor *secdesc;
927 struct winreg_String wkey, wkeyclass;
928 const char *path;
929 const char *subkeys[] = { SPOOL_DSDRIVER_KEY, SPOOL_DSSPOOLER_KEY, SPOOL_PRINTERDATA_KEY };
930 uint32_t i, count = ARRAY_SIZE(subkeys);
931 uint32_t info2_mask = 0;
932 WERROR result = WERR_OK;
933 TALLOC_CTX *tmp_ctx;
935 tmp_ctx = talloc_stackframe();
936 if (tmp_ctx == NULL) {
937 return WERR_NOMEM;
940 path = winreg_printer_data_keyname(tmp_ctx, sharename);
941 if (path == NULL) {
942 TALLOC_FREE(tmp_ctx);
943 return WERR_NOMEM;
946 ZERO_STRUCT(hive_hnd);
947 ZERO_STRUCT(key_hnd);
949 result = winreg_printer_openkey(tmp_ctx,
950 session_info,
951 msg_ctx,
952 &winreg_handle,
953 path,
955 false,
956 access_mask,
957 &hive_hnd,
958 &key_hnd);
959 if (W_ERROR_IS_OK(result)) {
960 DEBUG(2, ("winreg_create_printer: Skipping, %s already exists\n", path));
961 goto done;
962 } else if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
963 DEBUG(2, ("winreg_create_printer: Creating default values in %s\n", path));
964 } else if (!W_ERROR_IS_OK(result)) {
965 DEBUG(0, ("winreg_create_printer: Could not open key %s: %s\n",
966 path, win_errstr(result)));
967 goto done;
970 /* Create the main key */
971 result = winreg_printer_openkey(tmp_ctx,
972 session_info,
973 msg_ctx,
974 &winreg_handle,
975 path,
977 true,
978 access_mask,
979 &hive_hnd,
980 &key_hnd);
981 if (!W_ERROR_IS_OK(result)) {
982 DEBUG(0, ("winreg_create_printer_keys: Could not create key %s: %s\n",
983 path, win_errstr(result)));
984 goto done;
987 if (is_valid_policy_hnd(&key_hnd)) {
988 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &result);
991 /* Create subkeys */
992 for (i = 0; i < count; i++) {
993 NTSTATUS status;
994 enum winreg_CreateAction action = REG_ACTION_NONE;
996 ZERO_STRUCT(key_hnd);
997 ZERO_STRUCT(wkey);
999 wkey.name = talloc_asprintf(tmp_ctx, "%s\\%s", path, subkeys[i]);
1000 if (wkey.name == NULL) {
1001 result = WERR_NOMEM;
1002 goto done;
1005 ZERO_STRUCT(wkeyclass);
1006 wkeyclass.name = "";
1008 status = dcerpc_winreg_CreateKey(winreg_handle,
1009 tmp_ctx,
1010 &hive_hnd,
1011 wkey,
1012 wkeyclass,
1014 access_mask,
1015 NULL,
1016 &key_hnd,
1017 &action,
1018 &result);
1019 if (!NT_STATUS_IS_OK(status)) {
1020 result = ntstatus_to_werror(status);
1022 if (!W_ERROR_IS_OK(result)) {
1023 DEBUG(0, ("winreg_create_printer_keys: Could not create key %s: %s\n",
1024 wkey.name, win_errstr(result)));
1025 goto done;
1028 if (strequal(subkeys[i], SPOOL_DSSPOOLER_KEY)) {
1029 const char *dnssuffix;
1030 const char *longname;
1031 const char *uncname;
1033 status = dcerpc_winreg_set_sz(tmp_ctx,
1034 winreg_handle,
1035 &key_hnd,
1036 SPOOL_REG_PRINTERNAME,
1037 sharename,
1038 &result);
1039 if (!NT_STATUS_IS_OK(status)) {
1040 result = ntstatus_to_werror(status);
1042 if (!W_ERROR_IS_OK(result)) {
1043 goto done;
1046 status = dcerpc_winreg_set_sz(tmp_ctx,
1047 winreg_handle,
1048 &key_hnd,
1049 SPOOL_REG_SHORTSERVERNAME,
1050 global_myname(),
1051 &result);
1052 if (!NT_STATUS_IS_OK(status)) {
1053 result = ntstatus_to_werror(status);
1055 if (!W_ERROR_IS_OK(result)) {
1056 goto done;
1059 /* We make the assumption that the netbios name
1060 * is the same as the DNS name since the former
1061 * will be what we used to join the domain
1063 dnssuffix = get_mydnsdomname(tmp_ctx);
1064 if (dnssuffix != NULL && dnssuffix[0] != '\0') {
1065 longname = talloc_asprintf(tmp_ctx, "%s.%s", global_myname(), dnssuffix);
1066 } else {
1067 longname = talloc_strdup(tmp_ctx, global_myname());
1069 if (longname == NULL) {
1070 result = WERR_NOMEM;
1071 goto done;
1074 status = dcerpc_winreg_set_sz(tmp_ctx,
1075 winreg_handle,
1076 &key_hnd,
1077 SPOOL_REG_SERVERNAME,
1078 longname,
1079 &result);
1080 if (!NT_STATUS_IS_OK(status)) {
1081 result = ntstatus_to_werror(status);
1083 if (!W_ERROR_IS_OK(result)) {
1084 goto done;
1087 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
1088 longname, sharename);
1089 if (uncname == NULL) {
1090 result = WERR_NOMEM;
1091 goto done;
1094 status = dcerpc_winreg_set_sz(tmp_ctx,
1095 winreg_handle,
1096 &key_hnd,
1097 SPOOL_REG_UNCNAME,
1098 uncname,
1099 &result);
1100 if (!NT_STATUS_IS_OK(status)) {
1101 result = ntstatus_to_werror(status);
1103 if (!W_ERROR_IS_OK(result)) {
1104 goto done;
1107 status = dcerpc_winreg_set_dword(tmp_ctx,
1108 winreg_handle,
1109 &key_hnd,
1110 SPOOL_REG_VERSIONNUMBER,
1112 &result);
1113 if (!NT_STATUS_IS_OK(status)) {
1114 result = ntstatus_to_werror(status);
1116 if (!W_ERROR_IS_OK(result)) {
1117 goto done;
1120 status = dcerpc_winreg_set_dword(tmp_ctx,
1121 winreg_handle,
1122 &key_hnd,
1123 SPOOL_REG_PRINTSTARTTIME,
1125 &result);
1126 if (!NT_STATUS_IS_OK(status)) {
1127 result = ntstatus_to_werror(status);
1129 if (!W_ERROR_IS_OK(result)) {
1130 goto done;
1133 status = dcerpc_winreg_set_dword(tmp_ctx,
1134 winreg_handle,
1135 &key_hnd,
1136 SPOOL_REG_PRINTENDTIME,
1138 &result);
1139 if (!NT_STATUS_IS_OK(status)) {
1140 result = ntstatus_to_werror(status);
1142 if (!W_ERROR_IS_OK(result)) {
1143 goto done;
1146 status = dcerpc_winreg_set_dword(tmp_ctx,
1147 winreg_handle,
1148 &key_hnd,
1149 SPOOL_REG_PRIORITY,
1151 &result);
1152 if (!NT_STATUS_IS_OK(status)) {
1153 result = ntstatus_to_werror(status);
1155 if (!W_ERROR_IS_OK(result)) {
1156 goto done;
1159 status = dcerpc_winreg_set_dword(tmp_ctx,
1160 winreg_handle,
1161 &key_hnd,
1162 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
1164 &result);
1165 if (!NT_STATUS_IS_OK(status)) {
1166 result = ntstatus_to_werror(status);
1168 if (!W_ERROR_IS_OK(result)) {
1169 goto done;
1173 if (is_valid_policy_hnd(&key_hnd)) {
1174 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &result);
1177 info2 = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
1178 if (info2 == NULL) {
1179 result = WERR_NOMEM;
1180 goto done;
1183 info2->printername = sharename;
1184 if (info2->printername == NULL) {
1185 result = WERR_NOMEM;
1186 goto done;
1188 info2_mask |= SPOOLSS_PRINTER_INFO_PRINTERNAME;
1190 info2->sharename = sharename;
1191 info2_mask |= SPOOLSS_PRINTER_INFO_SHARENAME;
1193 info2->portname = SAMBA_PRINTER_PORT_NAME;
1194 info2_mask |= SPOOLSS_PRINTER_INFO_PORTNAME;
1196 info2->printprocessor = "winprint";
1197 info2_mask |= SPOOLSS_PRINTER_INFO_PRINTPROCESSOR;
1199 info2->datatype = "RAW";
1200 info2_mask |= SPOOLSS_PRINTER_INFO_DATATYPE;
1202 info2->comment = "";
1203 info2_mask |= SPOOLSS_PRINTER_INFO_COMMENT;
1205 info2->attributes = PRINTER_ATTRIBUTE_SAMBA;
1206 info2_mask |= SPOOLSS_PRINTER_INFO_ATTRIBUTES;
1208 info2->starttime = 0; /* Minutes since 12:00am GMT */
1209 info2_mask |= SPOOLSS_PRINTER_INFO_STARTTIME;
1211 info2->untiltime = 0; /* Minutes since 12:00am GMT */
1212 info2_mask |= SPOOLSS_PRINTER_INFO_UNTILTIME;
1214 info2->priority = 1;
1215 info2_mask |= SPOOLSS_PRINTER_INFO_PRIORITY;
1217 info2->defaultpriority = 1;
1218 info2_mask |= SPOOLSS_PRINTER_INFO_DEFAULTPRIORITY;
1220 result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
1221 if (!W_ERROR_IS_OK(result)) {
1222 goto done;
1224 info2_mask |= SPOOLSS_PRINTER_INFO_SECDESC;
1227 * Don't write a default Device Mode to the registry! The Device Mode is
1228 * only written to disk with a SetPrinter level 2 or 8.
1231 result = winreg_update_printer(tmp_ctx,
1232 session_info,
1233 msg_ctx,
1234 sharename,
1235 info2_mask,
1236 info2,
1237 NULL,
1238 secdesc);
1240 done:
1241 if (winreg_handle != NULL) {
1242 WERROR ignore;
1244 if (is_valid_policy_hnd(&key_hnd)) {
1245 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1247 if (is_valid_policy_hnd(&hive_hnd)) {
1248 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1252 talloc_free(tmp_ctx);
1253 return result;
1256 WERROR winreg_update_printer(TALLOC_CTX *mem_ctx,
1257 const struct auth_serversupplied_info *session_info,
1258 struct messaging_context *msg_ctx,
1259 const char *sharename,
1260 uint32_t info2_mask,
1261 struct spoolss_SetPrinterInfo2 *info2,
1262 struct spoolss_DeviceMode *devmode,
1263 struct security_descriptor *secdesc)
1265 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1266 struct dcerpc_binding_handle *winreg_handle = NULL;
1267 struct policy_handle hive_hnd, key_hnd;
1268 int snum = lp_servicenumber(sharename);
1269 enum ndr_err_code ndr_err;
1270 DATA_BLOB blob;
1271 char *path;
1272 WERROR result = WERR_OK;
1273 NTSTATUS status;
1274 TALLOC_CTX *tmp_ctx;
1276 tmp_ctx = talloc_stackframe();
1277 if (tmp_ctx == NULL) {
1278 return WERR_NOMEM;
1281 path = winreg_printer_data_keyname(tmp_ctx, sharename);
1282 if (path == NULL) {
1283 TALLOC_FREE(tmp_ctx);
1284 return WERR_NOMEM;
1287 ZERO_STRUCT(hive_hnd);
1288 ZERO_STRUCT(key_hnd);
1290 result = winreg_printer_openkey(tmp_ctx,
1291 session_info,
1292 msg_ctx,
1293 &winreg_handle,
1294 path,
1296 true,
1297 access_mask,
1298 &hive_hnd,
1299 &key_hnd);
1300 if (!W_ERROR_IS_OK(result)) {
1301 DEBUG(0, ("winreg_update_printer: Could not open key %s: %s\n",
1302 path, win_errstr(result)));
1303 goto done;
1306 if (info2_mask & SPOOLSS_PRINTER_INFO_ATTRIBUTES) {
1307 status = dcerpc_winreg_set_dword(tmp_ctx,
1308 winreg_handle,
1309 &key_hnd,
1310 "Attributes",
1311 info2->attributes,
1312 &result);
1313 if (!NT_STATUS_IS_OK(status)) {
1314 result = ntstatus_to_werror(status);
1316 if (!W_ERROR_IS_OK(result)) {
1317 goto done;
1321 #if 0
1322 if (info2_mask & SPOOLSS_PRINTER_INFO_AVERAGEPPM) {
1323 status = dcerpc_winreg_set_dword(tmp_ctx,
1324 winreg_handle,
1325 &key_hnd,
1326 "AveragePpm",
1327 info2->attributes,
1328 &result);
1329 if (!NT_STATUS_IS_OK(status)) {
1330 result = ntstatus_to_werror(status);
1332 if (!W_ERROR_IS_OK(result)) {
1333 goto done;
1336 #endif
1338 if (info2_mask & SPOOLSS_PRINTER_INFO_COMMENT) {
1339 status = dcerpc_winreg_set_sz(tmp_ctx,
1340 winreg_handle,
1341 &key_hnd,
1342 "Description",
1343 info2->comment,
1344 &result);
1345 if (!NT_STATUS_IS_OK(status)) {
1346 result = ntstatus_to_werror(status);
1348 if (!W_ERROR_IS_OK(result)) {
1349 goto done;
1353 if (info2_mask & SPOOLSS_PRINTER_INFO_DATATYPE) {
1354 status = dcerpc_winreg_set_sz(tmp_ctx,
1355 winreg_handle,
1356 &key_hnd,
1357 "Datatype",
1358 info2->datatype,
1359 &result);
1360 if (!NT_STATUS_IS_OK(status)) {
1361 result = ntstatus_to_werror(status);
1363 if (!W_ERROR_IS_OK(result)) {
1364 goto done;
1368 if (info2_mask & SPOOLSS_PRINTER_INFO_DEFAULTPRIORITY) {
1369 status = dcerpc_winreg_set_dword(tmp_ctx,
1370 winreg_handle,
1371 &key_hnd,
1372 "Default Priority",
1373 info2->defaultpriority,
1374 &result);
1375 if (!NT_STATUS_IS_OK(status)) {
1376 result = ntstatus_to_werror(status);
1378 if (!W_ERROR_IS_OK(result)) {
1379 goto done;
1383 if (info2_mask & SPOOLSS_PRINTER_INFO_DEVMODE) {
1385 * Some client drivers freak out if there is a NULL devmode
1386 * (probably the driver is not checking before accessing
1387 * the devmode pointer) --jerry
1389 if (devmode == NULL && lp_default_devmode(snum) && info2 != NULL) {
1390 result = spoolss_create_default_devmode(tmp_ctx,
1391 info2->printername,
1392 &devmode);
1393 if (!W_ERROR_IS_OK(result)) {
1394 goto done;
1398 if (devmode->size != (ndr_size_spoolss_DeviceMode(devmode, 0) - devmode->__driverextra_length)) {
1399 result = WERR_INVALID_PARAM;
1400 goto done;
1403 ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, devmode,
1404 (ndr_push_flags_fn_t) ndr_push_spoolss_DeviceMode);
1405 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1406 DEBUG(0, ("winreg_update_printer: Failed to marshall device mode\n"));
1407 result = WERR_NOMEM;
1408 goto done;
1411 status = dcerpc_winreg_set_binary(tmp_ctx,
1412 winreg_handle,
1413 &key_hnd,
1414 "Default DevMode",
1415 &blob,
1416 &result);
1417 if (!NT_STATUS_IS_OK(status)) {
1418 result = ntstatus_to_werror(status);
1420 if (!W_ERROR_IS_OK(result)) {
1421 goto done;
1425 if (info2_mask & SPOOLSS_PRINTER_INFO_DRIVERNAME) {
1426 status = dcerpc_winreg_set_sz(tmp_ctx,
1427 winreg_handle,
1428 &key_hnd,
1429 "Printer Driver",
1430 info2->drivername,
1431 &result);
1432 if (!NT_STATUS_IS_OK(status)) {
1433 result = ntstatus_to_werror(status);
1435 if (!W_ERROR_IS_OK(result)) {
1436 goto done;
1440 if (info2_mask & SPOOLSS_PRINTER_INFO_LOCATION) {
1441 status = dcerpc_winreg_set_sz(tmp_ctx,
1442 winreg_handle,
1443 &key_hnd,
1444 "Location",
1445 info2->location,
1446 &result);
1447 if (!NT_STATUS_IS_OK(status)) {
1448 result = ntstatus_to_werror(status);
1450 if (!W_ERROR_IS_OK(result)) {
1451 goto done;
1455 if (info2_mask & SPOOLSS_PRINTER_INFO_PARAMETERS) {
1456 status = dcerpc_winreg_set_sz(tmp_ctx,
1457 winreg_handle,
1458 &key_hnd,
1459 "Parameters",
1460 info2->parameters,
1461 &result);
1462 if (!NT_STATUS_IS_OK(status)) {
1463 result = ntstatus_to_werror(status);
1465 if (!W_ERROR_IS_OK(result)) {
1466 goto done;
1470 if (info2_mask & SPOOLSS_PRINTER_INFO_PORTNAME) {
1471 status = dcerpc_winreg_set_sz(tmp_ctx,
1472 winreg_handle,
1473 &key_hnd,
1474 "Port",
1475 info2->portname,
1476 &result);
1477 if (!NT_STATUS_IS_OK(status)) {
1478 result = ntstatus_to_werror(status);
1480 if (!W_ERROR_IS_OK(result)) {
1481 goto done;
1485 if (info2_mask & SPOOLSS_PRINTER_INFO_PRINTERNAME) {
1487 * in addprinter: no servername and the printer is the name
1488 * in setprinter: servername is \\server
1489 * and printer is \\server\\printer
1491 * Samba manages only local printers.
1492 * we currently don't support things like i
1493 * path=\\other_server\printer
1495 * We only store the printername, not \\server\printername
1497 const char *p = strrchr(info2->printername, '\\');
1498 if (p == NULL) {
1499 p = info2->printername;
1500 } else {
1501 p++;
1503 status = dcerpc_winreg_set_sz(tmp_ctx,
1504 winreg_handle,
1505 &key_hnd,
1506 "Name",
1508 &result);
1509 if (!NT_STATUS_IS_OK(status)) {
1510 result = ntstatus_to_werror(status);
1512 if (!W_ERROR_IS_OK(result)) {
1513 goto done;
1517 if (info2_mask & SPOOLSS_PRINTER_INFO_PRINTPROCESSOR) {
1518 status = dcerpc_winreg_set_sz(tmp_ctx,
1519 winreg_handle,
1520 &key_hnd,
1521 "Print Processor",
1522 info2->printprocessor,
1523 &result);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 result = ntstatus_to_werror(status);
1527 if (!W_ERROR_IS_OK(result)) {
1528 goto done;
1532 if (info2_mask & SPOOLSS_PRINTER_INFO_PRIORITY) {
1533 status = dcerpc_winreg_set_dword(tmp_ctx,
1534 winreg_handle,
1535 &key_hnd,
1536 "Priority",
1537 info2->priority,
1538 &result);
1539 if (!NT_STATUS_IS_OK(status)) {
1540 result = ntstatus_to_werror(status);
1542 if (!W_ERROR_IS_OK(result)) {
1543 goto done;
1547 if (info2_mask & SPOOLSS_PRINTER_INFO_SECDESC) {
1549 * We need a security descriptor, if it isn't specified by
1550 * AddPrinter{Ex} then create a default descriptor.
1552 if (secdesc == NULL) {
1553 result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
1554 if (!W_ERROR_IS_OK(result)) {
1555 goto done;
1558 result = winreg_set_printer_secdesc(tmp_ctx,
1559 session_info,
1560 msg_ctx,
1561 sharename,
1562 secdesc);
1563 if (!W_ERROR_IS_OK(result)) {
1564 goto done;
1568 if (info2_mask & SPOOLSS_PRINTER_INFO_SEPFILE) {
1569 status = dcerpc_winreg_set_sz(tmp_ctx,
1570 winreg_handle,
1571 &key_hnd,
1572 "Separator File",
1573 info2->sepfile,
1574 &result);
1575 if (!NT_STATUS_IS_OK(status)) {
1576 result = ntstatus_to_werror(status);
1578 if (!W_ERROR_IS_OK(result)) {
1579 goto done;
1583 if (info2_mask & SPOOLSS_PRINTER_INFO_SHARENAME) {
1584 status = dcerpc_winreg_set_sz(tmp_ctx,
1585 winreg_handle,
1586 &key_hnd,
1587 "Share Name",
1588 info2->sharename,
1589 &result);
1590 if (!NT_STATUS_IS_OK(status)) {
1591 result = ntstatus_to_werror(status);
1593 if (!W_ERROR_IS_OK(result)) {
1594 goto done;
1598 if (info2_mask & SPOOLSS_PRINTER_INFO_STARTTIME) {
1599 status = dcerpc_winreg_set_dword(tmp_ctx,
1600 winreg_handle,
1601 &key_hnd,
1602 "StartTime",
1603 info2->starttime,
1604 &result);
1605 if (!NT_STATUS_IS_OK(status)) {
1606 result = ntstatus_to_werror(status);
1608 if (!W_ERROR_IS_OK(result)) {
1609 goto done;
1613 if (info2_mask & SPOOLSS_PRINTER_INFO_STATUS) {
1614 status = dcerpc_winreg_set_dword(tmp_ctx,
1615 winreg_handle,
1616 &key_hnd,
1617 "Status",
1618 info2->status,
1619 &result);
1620 if (!NT_STATUS_IS_OK(status)) {
1621 result = ntstatus_to_werror(status);
1623 if (!W_ERROR_IS_OK(result)) {
1624 goto done;
1628 if (info2_mask & SPOOLSS_PRINTER_INFO_UNTILTIME) {
1629 status = dcerpc_winreg_set_dword(tmp_ctx,
1630 winreg_handle,
1631 &key_hnd,
1632 "UntilTime",
1633 info2->untiltime,
1634 &result);
1635 if (!NT_STATUS_IS_OK(status)) {
1636 result = ntstatus_to_werror(status);
1638 if (!W_ERROR_IS_OK(result)) {
1639 goto done;
1643 status = dcerpc_winreg_set_dword(tmp_ctx,
1644 winreg_handle,
1645 &key_hnd,
1646 "ChangeID",
1647 winreg_printer_rev_changeid(),
1648 &result);
1649 if (!NT_STATUS_IS_OK(status)) {
1650 result = ntstatus_to_werror(status);
1652 if (!W_ERROR_IS_OK(result)) {
1653 goto done;
1656 result = WERR_OK;
1657 done:
1658 if (winreg_handle != NULL) {
1659 WERROR ignore;
1661 if (is_valid_policy_hnd(&key_hnd)) {
1662 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1664 if (is_valid_policy_hnd(&hive_hnd)) {
1665 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1669 TALLOC_FREE(tmp_ctx);
1670 return result;
1673 WERROR winreg_get_printer(TALLOC_CTX *mem_ctx,
1674 const struct auth_serversupplied_info *session_info,
1675 struct messaging_context *msg_ctx,
1676 const char *printer,
1677 struct spoolss_PrinterInfo2 **pinfo2)
1679 struct spoolss_PrinterInfo2 *info2;
1680 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1681 struct dcerpc_binding_handle *winreg_handle = NULL;
1682 struct policy_handle hive_hnd, key_hnd;
1683 struct spoolss_PrinterEnumValues *enum_values = NULL;
1684 struct spoolss_PrinterEnumValues *v = NULL;
1685 enum ndr_err_code ndr_err;
1686 DATA_BLOB blob;
1687 int snum = lp_servicenumber(printer);
1688 uint32_t num_values = 0;
1689 uint32_t i;
1690 char *path;
1691 NTSTATUS status;
1692 WERROR result = WERR_OK;
1693 TALLOC_CTX *tmp_ctx;
1695 tmp_ctx = talloc_stackframe();
1696 if (tmp_ctx == NULL) {
1697 return WERR_NOMEM;
1700 path = winreg_printer_data_keyname(tmp_ctx, printer);
1701 if (path == NULL) {
1702 TALLOC_FREE(tmp_ctx);
1703 return WERR_NOMEM;
1706 result = winreg_printer_openkey(tmp_ctx,
1707 session_info,
1708 msg_ctx,
1709 &winreg_handle,
1710 path,
1712 false,
1713 access_mask,
1714 &hive_hnd,
1715 &key_hnd);
1716 if (!W_ERROR_IS_OK(result)) {
1717 DEBUG(2, ("winreg_get_printer: Could not open key %s: %s\n",
1718 path, win_errstr(result)));
1719 goto done;
1722 result = winreg_printer_enumvalues(tmp_ctx,
1723 winreg_handle,
1724 &key_hnd,
1725 &num_values,
1726 &enum_values);
1727 if (!W_ERROR_IS_OK(result)) {
1728 DEBUG(0, ("winreg_get_printer: Could not enumerate values in %s: %s\n",
1729 path, win_errstr(result)));
1730 goto done;
1733 info2 = talloc_zero(tmp_ctx, struct spoolss_PrinterInfo2);
1734 if (info2 == NULL) {
1735 result = WERR_NOMEM;
1736 goto done;
1739 FILL_STRING(info2, EMPTY_STRING, info2->servername);
1740 FILL_STRING(info2, EMPTY_STRING, info2->printername);
1741 FILL_STRING(info2, EMPTY_STRING, info2->sharename);
1742 FILL_STRING(info2, EMPTY_STRING, info2->portname);
1743 FILL_STRING(info2, EMPTY_STRING, info2->drivername);
1744 FILL_STRING(info2, EMPTY_STRING, info2->comment);
1745 FILL_STRING(info2, EMPTY_STRING, info2->location);
1746 FILL_STRING(info2, EMPTY_STRING, info2->sepfile);
1747 FILL_STRING(info2, EMPTY_STRING, info2->printprocessor);
1748 FILL_STRING(info2, EMPTY_STRING, info2->datatype);
1749 FILL_STRING(info2, EMPTY_STRING, info2->parameters);
1751 for (i = 0; i < num_values; i++) {
1752 v = &enum_values[i];
1754 result = winreg_enumval_to_sz(info2,
1756 "Name",
1757 &info2->printername);
1758 CHECK_ERROR(result);
1760 result = winreg_enumval_to_sz(info2,
1762 "Share Name",
1763 &info2->sharename);
1764 CHECK_ERROR(result);
1766 result = winreg_enumval_to_sz(info2,
1768 "Port",
1769 &info2->portname);
1770 CHECK_ERROR(result);
1772 result = winreg_enumval_to_sz(info2,
1774 "Description",
1775 &info2->comment);
1776 CHECK_ERROR(result);
1778 result = winreg_enumval_to_sz(info2,
1780 "Location",
1781 &info2->location);
1782 CHECK_ERROR(result);
1784 result = winreg_enumval_to_sz(info2,
1786 "Separator File",
1787 &info2->sepfile);
1788 CHECK_ERROR(result);
1790 result = winreg_enumval_to_sz(info2,
1792 "Print Processor",
1793 &info2->printprocessor);
1794 CHECK_ERROR(result);
1796 result = winreg_enumval_to_sz(info2,
1798 "Datatype",
1799 &info2->datatype);
1800 CHECK_ERROR(result);
1802 result = winreg_enumval_to_sz(info2,
1804 "Parameters",
1805 &info2->parameters);
1806 CHECK_ERROR(result);
1808 result = winreg_enumval_to_sz(info2,
1810 "Printer Driver",
1811 &info2->drivername);
1812 CHECK_ERROR(result);
1814 result = winreg_enumval_to_dword(info2,
1816 "Attributes",
1817 &info2->attributes);
1818 CHECK_ERROR(result);
1820 result = winreg_enumval_to_dword(info2,
1822 "Priority",
1823 &info2->priority);
1824 CHECK_ERROR(result);
1826 result = winreg_enumval_to_dword(info2,
1828 "Default Priority",
1829 &info2->defaultpriority);
1830 CHECK_ERROR(result);
1832 result = winreg_enumval_to_dword(info2,
1834 "StartTime",
1835 &info2->starttime);
1836 CHECK_ERROR(result);
1838 result = winreg_enumval_to_dword(info2,
1840 "UntilTime",
1841 &info2->untiltime);
1842 CHECK_ERROR(result);
1844 result = winreg_enumval_to_dword(info2,
1846 "Status",
1847 &info2->status);
1848 CHECK_ERROR(result);
1850 result = winreg_enumval_to_dword(info2,
1852 "StartTime",
1853 &info2->starttime);
1854 CHECK_ERROR(result);
1857 if (!W_ERROR_IS_OK(result)) {
1858 DEBUG(0, ("winreg_get_printer: winreg_enumval_to_TYPE() failed "
1859 "for %s: %s\n",
1860 v->value_name,
1861 win_errstr(result)));
1862 goto done;
1865 /* Construct the Device Mode */
1866 status = dcerpc_winreg_query_binary(tmp_ctx,
1867 winreg_handle,
1868 &key_hnd,
1869 "Default DevMode",
1870 &blob,
1871 &result);
1872 if (!NT_STATUS_IS_OK(status)) {
1873 result = ntstatus_to_werror(status);
1875 if (W_ERROR_IS_OK(result)) {
1876 info2->devmode = talloc_zero(info2, struct spoolss_DeviceMode);
1877 if (info2->devmode == NULL) {
1878 result = WERR_NOMEM;
1879 goto done;
1881 ndr_err = ndr_pull_struct_blob(&blob,
1882 info2->devmode,
1883 info2->devmode,
1884 (ndr_pull_flags_fn_t) ndr_pull_spoolss_DeviceMode);
1885 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1886 DEBUG(0, ("winreg_get_printer: Failed to unmarshall device mode\n"));
1887 result = WERR_NOMEM;
1888 goto done;
1892 if (info2->devmode == NULL && lp_default_devmode(snum)) {
1893 result = spoolss_create_default_devmode(info2,
1894 info2->printername,
1895 &info2->devmode);
1896 if (!W_ERROR_IS_OK(result)) {
1897 goto done;
1901 if (info2->devmode) {
1902 info2->devmode->size = ndr_size_spoolss_DeviceMode(info2->devmode, 0) - info2->devmode->driverextra_data.length;
1905 result = winreg_get_printer_secdesc(info2,
1906 session_info,
1907 msg_ctx,
1908 printer,
1909 &info2->secdesc);
1910 if (!W_ERROR_IS_OK(result)) {
1911 goto done;
1914 /* Fix for OS/2 drivers. */
1915 if (get_remote_arch() == RA_OS2) {
1916 spoolss_map_to_os2_driver(info2, &info2->drivername);
1919 if (pinfo2) {
1920 *pinfo2 = talloc_move(mem_ctx, &info2);
1923 result = WERR_OK;
1924 done:
1925 if (winreg_handle != NULL) {
1926 WERROR ignore;
1928 if (is_valid_policy_hnd(&key_hnd)) {
1929 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1931 if (is_valid_policy_hnd(&hive_hnd)) {
1932 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1936 TALLOC_FREE(tmp_ctx);
1937 return result;
1940 WERROR winreg_get_printer_secdesc(TALLOC_CTX *mem_ctx,
1941 const struct auth_serversupplied_info *session_info,
1942 struct messaging_context *msg_ctx,
1943 const char *sharename,
1944 struct spoolss_security_descriptor **psecdesc)
1946 struct spoolss_security_descriptor *secdesc;
1947 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1948 struct dcerpc_binding_handle *winreg_handle = NULL;
1949 struct policy_handle hive_hnd, key_hnd;
1950 const char *path;
1951 TALLOC_CTX *tmp_ctx;
1952 NTSTATUS status;
1953 WERROR result;
1955 tmp_ctx = talloc_stackframe();
1956 if (tmp_ctx == NULL) {
1957 return WERR_NOMEM;
1960 path = winreg_printer_data_keyname(tmp_ctx, sharename);
1961 if (path == NULL) {
1962 talloc_free(tmp_ctx);
1963 return WERR_NOMEM;
1966 ZERO_STRUCT(hive_hnd);
1967 ZERO_STRUCT(key_hnd);
1969 result = winreg_printer_openkey(tmp_ctx,
1970 session_info,
1971 msg_ctx,
1972 &winreg_handle,
1973 path,
1975 false,
1976 access_mask,
1977 &hive_hnd,
1978 &key_hnd);
1979 if (!W_ERROR_IS_OK(result)) {
1980 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1981 goto create_default;
1983 goto done;
1986 status = dcerpc_winreg_query_sd(tmp_ctx,
1987 winreg_handle,
1988 &key_hnd,
1989 "Security",
1990 &secdesc,
1991 &result);
1992 if (!NT_STATUS_IS_OK(status)) {
1993 result = ntstatus_to_werror(status);
1995 if (!W_ERROR_IS_OK(result)) {
1996 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1997 goto create_default;
1999 goto done;
2002 if (psecdesc) {
2003 *psecdesc = talloc_move(mem_ctx, &secdesc);
2006 result = WERR_OK;
2007 goto done;
2009 create_default:
2010 result = winreg_printer_openkey(tmp_ctx,
2011 session_info,
2012 msg_ctx,
2013 &winreg_handle,
2014 path,
2016 true,
2017 access_mask,
2018 &hive_hnd,
2019 &key_hnd);
2020 if (!W_ERROR_IS_OK(result)) {
2021 goto done;
2024 result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
2025 if (!W_ERROR_IS_OK(result)) {
2026 goto done;
2029 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
2030 this security descriptor has been created when winbindd was
2031 down. Take ownership of security descriptor. */
2032 if (dom_sid_equal(secdesc->owner_sid, &global_sid_World)) {
2033 struct dom_sid owner_sid;
2035 /* Change sd owner to workgroup administrator */
2037 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
2038 struct spoolss_security_descriptor *new_secdesc;
2039 size_t size;
2041 /* Create new sd */
2042 sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
2044 new_secdesc = make_sec_desc(tmp_ctx,
2045 secdesc->revision,
2046 secdesc->type,
2047 &owner_sid,
2048 secdesc->group_sid,
2049 secdesc->sacl,
2050 secdesc->dacl,
2051 &size);
2053 if (new_secdesc == NULL) {
2054 result = WERR_NOMEM;
2055 goto done;
2058 /* Swap with other one */
2059 secdesc = new_secdesc;
2063 status = dcerpc_winreg_set_sd(tmp_ctx,
2064 winreg_handle,
2065 &key_hnd,
2066 "Security",
2067 secdesc,
2068 &result);
2069 if (!NT_STATUS_IS_OK(status)) {
2070 result = ntstatus_to_werror(status);
2072 if (!W_ERROR_IS_OK(result)) {
2073 return result;
2076 if (psecdesc) {
2077 *psecdesc = talloc_move(mem_ctx, &secdesc);
2080 result = WERR_OK;
2081 done:
2082 if (winreg_handle != NULL) {
2083 WERROR ignore;
2085 if (is_valid_policy_hnd(&key_hnd)) {
2086 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2088 if (is_valid_policy_hnd(&hive_hnd)) {
2089 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2093 talloc_free(tmp_ctx);
2094 return result;
2097 WERROR winreg_set_printer_secdesc(TALLOC_CTX *mem_ctx,
2098 const struct auth_serversupplied_info *session_info,
2099 struct messaging_context *msg_ctx,
2100 const char *sharename,
2101 const struct spoolss_security_descriptor *secdesc)
2103 const struct spoolss_security_descriptor *new_secdesc = secdesc;
2104 struct spoolss_security_descriptor *old_secdesc;
2105 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2106 struct dcerpc_binding_handle *winreg_handle = NULL;
2107 struct policy_handle hive_hnd, key_hnd;
2108 const char *path;
2109 TALLOC_CTX *tmp_ctx;
2110 NTSTATUS status;
2111 WERROR result;
2113 tmp_ctx = talloc_stackframe();
2114 if (tmp_ctx == NULL) {
2115 return WERR_NOMEM;
2118 path = winreg_printer_data_keyname(tmp_ctx, sharename);
2119 if (path == NULL) {
2120 talloc_free(tmp_ctx);
2121 return WERR_NOMEM;
2125 * The old owner and group sids of the security descriptor are not
2126 * present when new ACEs are added or removed by changing printer
2127 * permissions through NT. If they are NULL in the new security
2128 * descriptor then copy them over from the old one.
2130 if (!secdesc->owner_sid || !secdesc->group_sid) {
2131 struct dom_sid *owner_sid, *group_sid;
2132 struct security_acl *dacl, *sacl;
2133 size_t size;
2135 result = winreg_get_printer_secdesc(tmp_ctx,
2136 session_info,
2137 msg_ctx,
2138 sharename,
2139 &old_secdesc);
2140 if (!W_ERROR_IS_OK(result)) {
2141 talloc_free(tmp_ctx);
2142 return result;
2145 /* Pick out correct owner and group sids */
2146 owner_sid = secdesc->owner_sid ?
2147 secdesc->owner_sid :
2148 old_secdesc->owner_sid;
2150 group_sid = secdesc->group_sid ?
2151 secdesc->group_sid :
2152 old_secdesc->group_sid;
2154 dacl = secdesc->dacl ?
2155 secdesc->dacl :
2156 old_secdesc->dacl;
2158 sacl = secdesc->sacl ?
2159 secdesc->sacl :
2160 old_secdesc->sacl;
2162 /* Make a deep copy of the security descriptor */
2163 new_secdesc = make_sec_desc(tmp_ctx,
2164 secdesc->revision,
2165 secdesc->type,
2166 owner_sid,
2167 group_sid,
2168 sacl,
2169 dacl,
2170 &size);
2171 if (new_secdesc == NULL) {
2172 talloc_free(tmp_ctx);
2173 return WERR_NOMEM;
2177 ZERO_STRUCT(hive_hnd);
2178 ZERO_STRUCT(key_hnd);
2180 result = winreg_printer_openkey(tmp_ctx,
2181 session_info,
2182 msg_ctx,
2183 &winreg_handle,
2184 path,
2186 false,
2187 access_mask,
2188 &hive_hnd,
2189 &key_hnd);
2190 if (!W_ERROR_IS_OK(result)) {
2191 goto done;
2194 status = dcerpc_winreg_set_sd(tmp_ctx,
2195 winreg_handle,
2196 &key_hnd,
2197 "Security",
2198 new_secdesc,
2199 &result);
2200 if (!NT_STATUS_IS_OK(status)) {
2201 result = ntstatus_to_werror(status);
2204 done:
2205 if (winreg_handle != NULL) {
2206 WERROR ignore;
2208 if (is_valid_policy_hnd(&key_hnd)) {
2209 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2211 if (is_valid_policy_hnd(&hive_hnd)) {
2212 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2216 talloc_free(tmp_ctx);
2217 return result;
2220 /* Set printer data over the winreg pipe. */
2221 WERROR winreg_set_printer_dataex(TALLOC_CTX *mem_ctx,
2222 const struct auth_serversupplied_info *session_info,
2223 struct messaging_context *msg_ctx,
2224 const char *printer,
2225 const char *key,
2226 const char *value,
2227 enum winreg_Type type,
2228 uint8_t *data,
2229 uint32_t data_size)
2231 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2232 struct dcerpc_binding_handle *winreg_handle = NULL;
2233 struct policy_handle hive_hnd, key_hnd;
2234 struct winreg_String wvalue = { 0, };
2235 char *path;
2236 WERROR result = WERR_OK;
2237 NTSTATUS status;
2238 TALLOC_CTX *tmp_ctx;
2240 tmp_ctx = talloc_stackframe();
2241 if (tmp_ctx == NULL) {
2242 return WERR_NOMEM;
2245 path = winreg_printer_data_keyname(tmp_ctx, printer);
2246 if (path == NULL) {
2247 TALLOC_FREE(tmp_ctx);
2248 return WERR_NOMEM;
2251 ZERO_STRUCT(hive_hnd);
2252 ZERO_STRUCT(key_hnd);
2254 DEBUG(8, ("winreg_set_printer_dataex: Open printer key %s, value %s, access_mask: 0x%05x for [%s]\n",
2255 key, value, access_mask, printer));
2256 result = winreg_printer_openkey(tmp_ctx,
2257 session_info,
2258 msg_ctx,
2259 &winreg_handle,
2260 path,
2261 key,
2262 true,
2263 access_mask,
2264 &hive_hnd,
2265 &key_hnd);
2266 if (!W_ERROR_IS_OK(result)) {
2267 DEBUG(0, ("winreg_set_printer_dataex: Could not open key %s: %s\n",
2268 key, win_errstr(result)));
2269 goto done;
2272 wvalue.name = value;
2273 status = dcerpc_winreg_SetValue(winreg_handle,
2274 tmp_ctx,
2275 &key_hnd,
2276 wvalue,
2277 type,
2278 data,
2279 data_size,
2280 &result);
2281 if (!NT_STATUS_IS_OK(status)) {
2282 DEBUG(0, ("winreg_set_printer_dataex: Could not set value %s: %s\n",
2283 value, nt_errstr(status)));
2284 result = ntstatus_to_werror(status);
2287 done:
2288 if (winreg_handle != NULL) {
2289 WERROR ignore;
2291 if (is_valid_policy_hnd(&key_hnd)) {
2292 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2294 if (is_valid_policy_hnd(&hive_hnd)) {
2295 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2299 TALLOC_FREE(tmp_ctx);
2300 return result;
2303 /* Get printer data over a winreg pipe. */
2304 WERROR winreg_get_printer_dataex(TALLOC_CTX *mem_ctx,
2305 const struct auth_serversupplied_info *session_info,
2306 struct messaging_context *msg_ctx,
2307 const char *printer,
2308 const char *key,
2309 const char *value,
2310 enum winreg_Type *type,
2311 uint8_t **data,
2312 uint32_t *data_size)
2314 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2315 struct dcerpc_binding_handle *winreg_handle = NULL;
2316 struct policy_handle hive_hnd, key_hnd;
2317 struct winreg_String wvalue;
2318 enum winreg_Type type_in = REG_NONE;
2319 char *path;
2320 uint8_t *data_in = NULL;
2321 uint32_t data_in_size = 0;
2322 uint32_t value_len = 0;
2323 WERROR result = WERR_OK;
2324 NTSTATUS status;
2325 TALLOC_CTX *tmp_ctx;
2327 tmp_ctx = talloc_stackframe();
2328 if (tmp_ctx == NULL) {
2329 return WERR_NOMEM;
2332 path = winreg_printer_data_keyname(tmp_ctx, printer);
2333 if (path == NULL) {
2334 TALLOC_FREE(tmp_ctx);
2335 return WERR_NOMEM;
2338 ZERO_STRUCT(hive_hnd);
2339 ZERO_STRUCT(key_hnd);
2341 result = winreg_printer_openkey(tmp_ctx,
2342 session_info,
2343 msg_ctx,
2344 &winreg_handle,
2345 path,
2346 key,
2347 false,
2348 access_mask,
2349 &hive_hnd,
2350 &key_hnd);
2351 if (!W_ERROR_IS_OK(result)) {
2352 DEBUG(2, ("winreg_get_printer_dataex: Could not open key %s: %s\n",
2353 key, win_errstr(result)));
2354 goto done;
2357 wvalue.name = value;
2360 * call QueryValue once with data == NULL to get the
2361 * needed memory size to be allocated, then allocate
2362 * data buffer and call again.
2364 status = dcerpc_winreg_QueryValue(winreg_handle,
2365 tmp_ctx,
2366 &key_hnd,
2367 &wvalue,
2368 &type_in,
2369 NULL,
2370 &data_in_size,
2371 &value_len,
2372 &result);
2373 if (!NT_STATUS_IS_OK(status)) {
2374 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2375 value, nt_errstr(status)));
2376 result = ntstatus_to_werror(status);
2377 goto done;
2379 if (!W_ERROR_IS_OK(result)) {
2380 goto done;
2383 data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
2384 if (data_in == NULL) {
2385 result = WERR_NOMEM;
2386 goto done;
2388 value_len = 0;
2390 status = dcerpc_winreg_QueryValue(winreg_handle,
2391 tmp_ctx,
2392 &key_hnd,
2393 &wvalue,
2394 &type_in,
2395 data_in,
2396 &data_in_size,
2397 &value_len,
2398 &result);
2399 if (!NT_STATUS_IS_OK(status)) {
2400 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2401 value, nt_errstr(status)));
2402 result = ntstatus_to_werror(status);
2403 goto done;
2405 if (!W_ERROR_IS_OK(result)) {
2406 goto done;
2409 *type = type_in;
2410 *data_size = data_in_size;
2411 if (data_in_size) {
2412 *data = talloc_move(mem_ctx, &data_in);
2415 result = WERR_OK;
2416 done:
2417 if (winreg_handle != NULL) {
2418 WERROR ignore;
2420 if (is_valid_policy_hnd(&key_hnd)) {
2421 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2423 if (is_valid_policy_hnd(&hive_hnd)) {
2424 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2428 TALLOC_FREE(tmp_ctx);
2429 return result;
2432 /* Enumerate on the values of a given key and provide the data. */
2433 WERROR winreg_enum_printer_dataex(TALLOC_CTX *mem_ctx,
2434 const struct auth_serversupplied_info *session_info,
2435 struct messaging_context *msg_ctx,
2436 const char *printer,
2437 const char *key,
2438 uint32_t *pnum_values,
2439 struct spoolss_PrinterEnumValues **penum_values)
2441 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2442 struct dcerpc_binding_handle *winreg_handle = NULL;
2443 struct policy_handle hive_hnd, key_hnd;
2445 struct spoolss_PrinterEnumValues *enum_values = NULL;
2446 uint32_t num_values = 0;
2447 char *path;
2448 WERROR result = WERR_OK;
2450 TALLOC_CTX *tmp_ctx;
2452 tmp_ctx = talloc_stackframe();
2453 if (tmp_ctx == NULL) {
2454 return WERR_NOMEM;
2457 path = winreg_printer_data_keyname(tmp_ctx, printer);
2458 if (path == NULL) {
2459 TALLOC_FREE(tmp_ctx);
2460 return WERR_NOMEM;
2463 result = winreg_printer_openkey(tmp_ctx,
2464 session_info,
2465 msg_ctx,
2466 &winreg_handle,
2467 path,
2468 key,
2469 false,
2470 access_mask,
2471 &hive_hnd,
2472 &key_hnd);
2473 if (!W_ERROR_IS_OK(result)) {
2474 DEBUG(2, ("winreg_enum_printer_dataex: Could not open key %s: %s\n",
2475 key, win_errstr(result)));
2476 goto done;
2479 result = winreg_printer_enumvalues(tmp_ctx,
2480 winreg_handle,
2481 &key_hnd,
2482 &num_values,
2483 &enum_values);
2484 if (!W_ERROR_IS_OK(result)) {
2485 DEBUG(0, ("winreg_enum_printer_dataex: Could not enumerate values in %s: %s\n",
2486 key, win_errstr(result)));
2487 goto done;
2490 *pnum_values = num_values;
2491 if (penum_values) {
2492 *penum_values = talloc_move(mem_ctx, &enum_values);
2495 result = WERR_OK;
2496 done:
2497 if (winreg_handle != NULL) {
2498 WERROR ignore;
2500 if (is_valid_policy_hnd(&key_hnd)) {
2501 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2503 if (is_valid_policy_hnd(&hive_hnd)) {
2504 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2508 TALLOC_FREE(tmp_ctx);
2509 return result;
2512 /* Delete printer data over a winreg pipe. */
2513 WERROR winreg_delete_printer_dataex(TALLOC_CTX *mem_ctx,
2514 const struct auth_serversupplied_info *session_info,
2515 struct messaging_context *msg_ctx,
2516 const char *printer,
2517 const char *key,
2518 const char *value)
2520 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2521 struct dcerpc_binding_handle *winreg_handle = NULL;
2522 struct policy_handle hive_hnd, key_hnd;
2523 struct winreg_String wvalue = { 0, };
2524 char *path;
2525 WERROR result = WERR_OK;
2526 NTSTATUS status;
2528 TALLOC_CTX *tmp_ctx;
2530 tmp_ctx = talloc_stackframe();
2531 if (tmp_ctx == NULL) {
2532 return WERR_NOMEM;
2535 path = winreg_printer_data_keyname(tmp_ctx, printer);
2536 if (path == NULL) {
2537 TALLOC_FREE(tmp_ctx);
2538 return WERR_NOMEM;
2541 ZERO_STRUCT(hive_hnd);
2542 ZERO_STRUCT(key_hnd);
2544 result = winreg_printer_openkey(tmp_ctx,
2545 session_info,
2546 msg_ctx,
2547 &winreg_handle,
2548 path,
2549 key,
2550 false,
2551 access_mask,
2552 &hive_hnd,
2553 &key_hnd);
2554 if (!W_ERROR_IS_OK(result)) {
2555 DEBUG(0, ("winreg_delete_printer_dataex: Could not open key %s: %s\n",
2556 key, win_errstr(result)));
2557 goto done;
2560 wvalue.name = value;
2561 status = dcerpc_winreg_DeleteValue(winreg_handle,
2562 tmp_ctx,
2563 &key_hnd,
2564 wvalue,
2565 &result);
2566 if (!NT_STATUS_IS_OK(status)) {
2567 DEBUG(0, ("winreg_delete_printer_dataex: Could not delete value %s: %s\n",
2568 value, nt_errstr(status)));
2569 result = ntstatus_to_werror(status);
2572 done:
2573 if (winreg_handle != NULL) {
2574 WERROR ignore;
2576 if (is_valid_policy_hnd(&key_hnd)) {
2577 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2579 if (is_valid_policy_hnd(&hive_hnd)) {
2580 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2584 TALLOC_FREE(tmp_ctx);
2585 return result;
2588 /* Enumerate on the subkeys of a given key and provide the data. */
2589 WERROR winreg_enum_printer_key(TALLOC_CTX *mem_ctx,
2590 const struct auth_serversupplied_info *session_info,
2591 struct messaging_context *msg_ctx,
2592 const char *printer,
2593 const char *key,
2594 uint32_t *pnum_subkeys,
2595 const char ***psubkeys)
2597 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2598 struct dcerpc_binding_handle *winreg_handle = NULL;
2599 struct policy_handle hive_hnd, key_hnd;
2600 char *path;
2601 const char **subkeys = NULL;
2602 uint32_t num_subkeys = -1;
2604 WERROR result = WERR_OK;
2605 NTSTATUS status;
2607 TALLOC_CTX *tmp_ctx;
2609 tmp_ctx = talloc_stackframe();
2610 if (tmp_ctx == NULL) {
2611 return WERR_NOMEM;
2614 path = winreg_printer_data_keyname(tmp_ctx, printer);
2615 if (path == NULL) {
2616 TALLOC_FREE(tmp_ctx);
2617 return WERR_NOMEM;
2620 ZERO_STRUCT(hive_hnd);
2621 ZERO_STRUCT(key_hnd);
2623 result = winreg_printer_openkey(tmp_ctx,
2624 session_info,
2625 msg_ctx,
2626 &winreg_handle,
2627 path,
2628 key,
2629 false,
2630 access_mask,
2631 &hive_hnd,
2632 &key_hnd);
2633 if (!W_ERROR_IS_OK(result)) {
2634 DEBUG(2, ("winreg_enum_printer_key: Could not open key %s: %s\n",
2635 key, win_errstr(result)));
2636 goto done;
2639 status = dcerpc_winreg_enum_keys(tmp_ctx,
2640 winreg_handle,
2641 &key_hnd,
2642 &num_subkeys,
2643 &subkeys,
2644 &result);
2645 if (!NT_STATUS_IS_OK(status)) {
2646 result = ntstatus_to_werror(status);
2648 if (!W_ERROR_IS_OK(result)) {
2649 DEBUG(0, ("winreg_enum_printer_key: Could not enumerate subkeys in %s: %s\n",
2650 key, win_errstr(result)));
2651 goto done;
2654 *pnum_subkeys = num_subkeys;
2655 if (psubkeys) {
2656 *psubkeys = talloc_move(mem_ctx, &subkeys);
2659 result = WERR_OK;
2660 done:
2661 if (winreg_handle != NULL) {
2662 WERROR ignore;
2664 if (is_valid_policy_hnd(&key_hnd)) {
2665 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2667 if (is_valid_policy_hnd(&hive_hnd)) {
2668 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2672 TALLOC_FREE(tmp_ctx);
2673 return result;
2676 /* Delete a key with subkeys of a given printer. */
2677 WERROR winreg_delete_printer_key(TALLOC_CTX *mem_ctx,
2678 const struct auth_serversupplied_info *session_info,
2679 struct messaging_context *msg_ctx,
2680 const char *printer,
2681 const char *key)
2683 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2684 struct dcerpc_binding_handle *winreg_handle = NULL;
2685 struct policy_handle hive_hnd, key_hnd;
2686 char *keyname;
2687 char *path;
2688 WERROR result;
2689 TALLOC_CTX *tmp_ctx;
2691 tmp_ctx = talloc_stackframe();
2692 if (tmp_ctx == NULL) {
2693 return WERR_NOMEM;
2696 path = winreg_printer_data_keyname(tmp_ctx, printer);
2697 if (path == NULL) {
2698 TALLOC_FREE(tmp_ctx);
2699 return WERR_NOMEM;
2702 result = winreg_printer_openkey(tmp_ctx,
2703 session_info,
2704 msg_ctx,
2705 &winreg_handle,
2706 path,
2707 key,
2708 false,
2709 access_mask,
2710 &hive_hnd,
2711 &key_hnd);
2712 if (!W_ERROR_IS_OK(result)) {
2713 /* key doesn't exist */
2714 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2715 result = WERR_OK;
2716 goto done;
2719 DEBUG(0, ("winreg_delete_printer_key: Could not open key %s: %s\n",
2720 key, win_errstr(result)));
2721 goto done;
2724 if (is_valid_policy_hnd(&key_hnd)) {
2725 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &result);
2728 if (key == NULL || key[0] == '\0') {
2729 keyname = path;
2730 } else {
2731 keyname = talloc_asprintf(tmp_ctx,
2732 "%s\\%s",
2733 path,
2734 key);
2735 if (keyname == NULL) {
2736 result = WERR_NOMEM;
2737 goto done;
2741 result = winreg_printer_delete_subkeys(tmp_ctx,
2742 winreg_handle,
2743 &hive_hnd,
2744 access_mask,
2745 keyname);
2746 if (!W_ERROR_IS_OK(result)) {
2747 DEBUG(0, ("winreg_delete_printer_key: Could not delete key %s: %s\n",
2748 key, win_errstr(result)));
2749 goto done;
2752 done:
2753 if (winreg_handle != NULL) {
2754 WERROR ignore;
2756 if (is_valid_policy_hnd(&key_hnd)) {
2757 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2759 if (is_valid_policy_hnd(&hive_hnd)) {
2760 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2764 TALLOC_FREE(tmp_ctx);
2765 return result;
2768 WERROR winreg_printer_update_changeid(TALLOC_CTX *mem_ctx,
2769 const struct auth_serversupplied_info *session_info,
2770 struct messaging_context *msg_ctx,
2771 const char *printer)
2773 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2774 struct dcerpc_binding_handle *winreg_handle = NULL;
2775 struct policy_handle hive_hnd, key_hnd;
2776 char *path;
2777 NTSTATUS status;
2778 WERROR result;
2779 TALLOC_CTX *tmp_ctx;
2781 tmp_ctx = talloc_stackframe();
2782 if (tmp_ctx == NULL) {
2783 return WERR_NOMEM;
2786 path = winreg_printer_data_keyname(tmp_ctx, printer);
2787 if (path == NULL) {
2788 TALLOC_FREE(tmp_ctx);
2789 return WERR_NOMEM;
2792 ZERO_STRUCT(hive_hnd);
2793 ZERO_STRUCT(key_hnd);
2795 result = winreg_printer_openkey(tmp_ctx,
2796 session_info,
2797 msg_ctx,
2798 &winreg_handle,
2799 path,
2801 false,
2802 access_mask,
2803 &hive_hnd,
2804 &key_hnd);
2805 if (!W_ERROR_IS_OK(result)) {
2806 DEBUG(0, ("winreg_printer_update_changeid: Could not open key %s: %s\n",
2807 path, win_errstr(result)));
2808 goto done;
2811 status = dcerpc_winreg_set_dword(tmp_ctx,
2812 winreg_handle,
2813 &key_hnd,
2814 "ChangeID",
2815 winreg_printer_rev_changeid(),
2816 &result);
2817 if (!NT_STATUS_IS_OK(status)) {
2818 result = ntstatus_to_werror(status);
2820 if (!W_ERROR_IS_OK(result)) {
2821 goto done;
2824 result = WERR_OK;
2825 done:
2826 if (winreg_handle != NULL) {
2827 WERROR ignore;
2829 if (is_valid_policy_hnd(&key_hnd)) {
2830 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2832 if (is_valid_policy_hnd(&hive_hnd)) {
2833 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2837 TALLOC_FREE(tmp_ctx);
2838 return result;
2841 WERROR winreg_printer_get_changeid(TALLOC_CTX *mem_ctx,
2842 const struct auth_serversupplied_info *session_info,
2843 struct messaging_context *msg_ctx,
2844 const char *printer,
2845 uint32_t *pchangeid)
2847 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2848 struct dcerpc_binding_handle *winreg_handle = NULL;
2849 struct policy_handle hive_hnd, key_hnd;
2850 uint32_t changeid = 0;
2851 char *path;
2852 NTSTATUS status;
2853 WERROR result;
2854 TALLOC_CTX *tmp_ctx;
2856 tmp_ctx = talloc_stackframe();
2857 if (tmp_ctx == NULL) {
2858 return WERR_NOMEM;
2861 path = winreg_printer_data_keyname(tmp_ctx, printer);
2862 if (path == NULL) {
2863 TALLOC_FREE(tmp_ctx);
2864 return WERR_NOMEM;
2867 ZERO_STRUCT(hive_hnd);
2868 ZERO_STRUCT(key_hnd);
2870 result = winreg_printer_openkey(tmp_ctx,
2871 session_info,
2872 msg_ctx,
2873 &winreg_handle,
2874 path,
2876 false,
2877 access_mask,
2878 &hive_hnd,
2879 &key_hnd);
2880 if (!W_ERROR_IS_OK(result)) {
2881 DEBUG(2, ("winreg_printer_get_changeid: Could not open key %s: %s\n",
2882 path, win_errstr(result)));
2883 goto done;
2886 DEBUG(10, ("winreg_printer_get_changeid: get changeid from %s\n", path));
2888 status = dcerpc_winreg_query_dword(tmp_ctx,
2889 winreg_handle,
2890 &key_hnd,
2891 "ChangeID",
2892 &changeid,
2893 &result);
2894 if (!NT_STATUS_IS_OK(status)) {
2895 result = ntstatus_to_werror(status);
2897 if (!W_ERROR_IS_OK(result)) {
2898 goto done;
2901 if (pchangeid) {
2902 *pchangeid = changeid;
2905 result = WERR_OK;
2906 done:
2907 if (winreg_handle != NULL) {
2908 WERROR ignore;
2910 if (is_valid_policy_hnd(&key_hnd)) {
2911 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2913 if (is_valid_policy_hnd(&hive_hnd)) {
2914 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2918 TALLOC_FREE(tmp_ctx);
2919 return result;
2923 * The special behaviour of the spoolss forms is documented at the website:
2925 * Managing Win32 Printserver Forms
2926 * http://unixwiz.net/techtips/winspooler-forms.html
2929 WERROR winreg_printer_addform1(TALLOC_CTX *mem_ctx,
2930 const struct auth_serversupplied_info *session_info,
2931 struct messaging_context *msg_ctx,
2932 struct spoolss_AddFormInfo1 *form)
2934 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2935 struct dcerpc_binding_handle *winreg_handle = NULL;
2936 struct policy_handle hive_hnd, key_hnd;
2937 struct winreg_String wvalue = { 0, };
2938 DATA_BLOB blob;
2939 uint32_t num_info = 0;
2940 union spoolss_FormInfo *info = NULL;
2941 uint32_t i;
2942 WERROR result;
2943 NTSTATUS status;
2944 TALLOC_CTX *tmp_ctx;
2946 tmp_ctx = talloc_stackframe();
2947 if (tmp_ctx == NULL) {
2948 return WERR_NOMEM;
2951 ZERO_STRUCT(hive_hnd);
2952 ZERO_STRUCT(key_hnd);
2954 result = winreg_printer_openkey(tmp_ctx,
2955 session_info,
2956 msg_ctx,
2957 &winreg_handle,
2958 TOP_LEVEL_CONTROL_FORMS_KEY,
2960 true,
2961 access_mask,
2962 &hive_hnd,
2963 &key_hnd);
2964 if (!W_ERROR_IS_OK(result)) {
2965 DEBUG(0, ("winreg_printer_addform1: Could not open key %s: %s\n",
2966 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2967 goto done;
2970 result = winreg_printer_enumforms1(tmp_ctx, session_info, msg_ctx,
2971 &num_info, &info);
2972 if (!W_ERROR_IS_OK(result)) {
2973 DEBUG(0, ("winreg_printer_addform: Could not enum keys %s: %s\n",
2974 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2975 goto done;
2978 /* If form name already exists or is builtin return ALREADY_EXISTS */
2979 for (i = 0; i < num_info; i++) {
2980 if (strequal(info[i].info1.form_name, form->form_name)) {
2981 result = WERR_FILE_EXISTS;
2982 goto done;
2986 wvalue.name = form->form_name;
2988 blob = data_blob_talloc(tmp_ctx, NULL, 32);
2989 SIVAL(blob.data, 0, form->size.width);
2990 SIVAL(blob.data, 4, form->size.height);
2991 SIVAL(blob.data, 8, form->area.left);
2992 SIVAL(blob.data, 12, form->area.top);
2993 SIVAL(blob.data, 16, form->area.right);
2994 SIVAL(blob.data, 20, form->area.bottom);
2995 SIVAL(blob.data, 24, num_info + 1); /* FIXME */
2996 SIVAL(blob.data, 28, form->flags);
2998 status = dcerpc_winreg_SetValue(winreg_handle,
2999 tmp_ctx,
3000 &key_hnd,
3001 wvalue,
3002 REG_BINARY,
3003 blob.data,
3004 blob.length,
3005 &result);
3006 if (!NT_STATUS_IS_OK(status)) {
3007 DEBUG(0, ("winreg_printer_addform1: Could not set value %s: %s\n",
3008 wvalue.name, nt_errstr(status)));
3009 result = ntstatus_to_werror(status);
3012 done:
3013 if (winreg_handle != NULL) {
3014 WERROR ignore;
3016 if (is_valid_policy_hnd(&key_hnd)) {
3017 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3019 if (is_valid_policy_hnd(&hive_hnd)) {
3020 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3024 TALLOC_FREE(info);
3025 TALLOC_FREE(tmp_ctx);
3026 return result;
3029 WERROR winreg_printer_enumforms1(TALLOC_CTX *mem_ctx,
3030 const struct auth_serversupplied_info *session_info,
3031 struct messaging_context *msg_ctx,
3032 uint32_t *pnum_info,
3033 union spoolss_FormInfo **pinfo)
3035 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3036 struct dcerpc_binding_handle *winreg_handle = NULL;
3037 struct policy_handle hive_hnd, key_hnd;
3038 union spoolss_FormInfo *info;
3039 struct spoolss_PrinterEnumValues *enum_values = NULL;
3040 uint32_t num_values = 0;
3041 uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
3042 uint32_t i;
3043 WERROR result;
3044 TALLOC_CTX *tmp_ctx;
3046 tmp_ctx = talloc_stackframe();
3047 if (tmp_ctx == NULL) {
3048 return WERR_NOMEM;
3051 ZERO_STRUCT(hive_hnd);
3052 ZERO_STRUCT(key_hnd);
3054 result = winreg_printer_openkey(tmp_ctx,
3055 session_info,
3056 msg_ctx,
3057 &winreg_handle,
3058 TOP_LEVEL_CONTROL_FORMS_KEY,
3060 true,
3061 access_mask,
3062 &hive_hnd,
3063 &key_hnd);
3064 if (!W_ERROR_IS_OK(result)) {
3065 /* key doesn't exist */
3066 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
3067 result = WERR_OK;
3068 goto done;
3071 DEBUG(0, ("winreg_printer_enumforms1: Could not open key %s: %s\n",
3072 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3073 goto done;
3076 result = winreg_printer_enumvalues(tmp_ctx,
3077 winreg_handle,
3078 &key_hnd,
3079 &num_values,
3080 &enum_values);
3081 if (!W_ERROR_IS_OK(result)) {
3082 DEBUG(0, ("winreg_printer_enumforms1: Could not enumerate values in %s: %s\n",
3083 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3084 goto done;
3087 info = TALLOC_ARRAY(tmp_ctx, union spoolss_FormInfo, num_builtin + num_values);
3088 if (info == NULL) {
3089 result = WERR_NOMEM;
3090 goto done;
3093 /* Enumerate BUILTIN forms */
3094 for (i = 0; i < num_builtin; i++) {
3095 info[i].info1 = builtin_forms1[i];
3098 /* Enumerate registry forms */
3099 for (i = 0; i < num_values; i++) {
3100 union spoolss_FormInfo val;
3102 if (enum_values[i].type != REG_BINARY ||
3103 enum_values[i].data_length != 32) {
3104 continue;
3107 val.info1.form_name = talloc_strdup(info, enum_values[i].value_name);
3108 if (val.info1.form_name == NULL) {
3109 result = WERR_NOMEM;
3110 goto done;
3113 val.info1.size.width = IVAL(enum_values[i].data->data, 0);
3114 val.info1.size.height = IVAL(enum_values[i].data->data, 4);
3115 val.info1.area.left = IVAL(enum_values[i].data->data, 8);
3116 val.info1.area.top = IVAL(enum_values[i].data->data, 12);
3117 val.info1.area.right = IVAL(enum_values[i].data->data, 16);
3118 val.info1.area.bottom = IVAL(enum_values[i].data->data, 20);
3119 /* skip form index IVAL(enum_values[i].data->data, 24)));*/
3120 val.info1.flags = (enum spoolss_FormFlags) IVAL(enum_values[i].data->data, 28);
3122 info[i + num_builtin] = val;
3125 *pnum_info = num_builtin + num_values;
3126 if (pinfo) {
3127 *pinfo = talloc_move(mem_ctx, &info);
3130 done:
3131 if (winreg_handle != NULL) {
3132 WERROR ignore;
3134 if (is_valid_policy_hnd(&key_hnd)) {
3135 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3137 if (is_valid_policy_hnd(&hive_hnd)) {
3138 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3142 TALLOC_FREE(enum_values);
3143 TALLOC_FREE(tmp_ctx);
3144 return result;
3147 WERROR winreg_printer_deleteform1(TALLOC_CTX *mem_ctx,
3148 const struct auth_serversupplied_info *session_info,
3149 struct messaging_context *msg_ctx,
3150 const char *form_name)
3152 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3153 struct dcerpc_binding_handle *winreg_handle = NULL;
3154 struct policy_handle hive_hnd, key_hnd;
3155 struct winreg_String wvalue = { 0, };
3156 uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
3157 uint32_t i;
3158 WERROR result = WERR_OK;
3159 NTSTATUS status;
3160 TALLOC_CTX *tmp_ctx;
3162 for (i = 0; i < num_builtin; i++) {
3163 if (strequal(builtin_forms1[i].form_name, form_name)) {
3164 return WERR_INVALID_PARAMETER;
3168 tmp_ctx = talloc_stackframe();
3169 if (tmp_ctx == NULL) {
3170 return WERR_NOMEM;
3173 ZERO_STRUCT(hive_hnd);
3174 ZERO_STRUCT(key_hnd);
3176 result = winreg_printer_openkey(tmp_ctx,
3177 session_info,
3178 msg_ctx,
3179 &winreg_handle,
3180 TOP_LEVEL_CONTROL_FORMS_KEY,
3182 false,
3183 access_mask,
3184 &hive_hnd,
3185 &key_hnd);
3186 if (!W_ERROR_IS_OK(result)) {
3187 DEBUG(0, ("winreg_printer_deleteform1: Could not open key %s: %s\n",
3188 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3189 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
3190 result = WERR_INVALID_FORM_NAME;
3192 goto done;
3195 wvalue.name = form_name;
3196 status = dcerpc_winreg_DeleteValue(winreg_handle,
3197 tmp_ctx,
3198 &key_hnd,
3199 wvalue,
3200 &result);
3201 if (!NT_STATUS_IS_OK(status)) {
3202 /* If the value doesn't exist, return WERR_INVALID_FORM_NAME */
3203 DEBUG(0, ("winreg_printer_delteform1: Could not delete value %s: %s\n",
3204 wvalue.name, nt_errstr(status)));
3205 result = ntstatus_to_werror(status);
3206 goto done;
3209 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
3210 result = WERR_INVALID_FORM_NAME;
3213 done:
3214 if (winreg_handle != NULL) {
3215 WERROR ignore;
3217 if (is_valid_policy_hnd(&key_hnd)) {
3218 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3220 if (is_valid_policy_hnd(&hive_hnd)) {
3221 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3225 TALLOC_FREE(tmp_ctx);
3226 return result;
3229 WERROR winreg_printer_setform1(TALLOC_CTX *mem_ctx,
3230 const struct auth_serversupplied_info *session_info,
3231 struct messaging_context *msg_ctx,
3232 const char *form_name,
3233 struct spoolss_AddFormInfo1 *form)
3235 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3236 struct dcerpc_binding_handle *winreg_handle = NULL;
3237 struct policy_handle hive_hnd, key_hnd;
3238 struct winreg_String wvalue = { 0, };
3239 DATA_BLOB blob;
3240 uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
3241 uint32_t i;
3242 WERROR result;
3243 NTSTATUS status;
3244 TALLOC_CTX *tmp_ctx = NULL;
3246 for (i = 0; i < num_builtin; i++) {
3247 if (strequal(builtin_forms1[i].form_name, form->form_name)) {
3248 result = WERR_INVALID_PARAM;
3249 goto done;
3253 tmp_ctx = talloc_stackframe();
3254 if (tmp_ctx == NULL) {
3255 return WERR_NOMEM;
3258 ZERO_STRUCT(hive_hnd);
3259 ZERO_STRUCT(key_hnd);
3261 result = winreg_printer_openkey(tmp_ctx,
3262 session_info,
3263 msg_ctx,
3264 &winreg_handle,
3265 TOP_LEVEL_CONTROL_FORMS_KEY,
3267 true,
3268 access_mask,
3269 &hive_hnd,
3270 &key_hnd);
3271 if (!W_ERROR_IS_OK(result)) {
3272 DEBUG(0, ("winreg_printer_setform1: Could not open key %s: %s\n",
3273 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3274 goto done;
3277 /* If form_name != form->form_name then we renamed the form */
3278 if (strequal(form_name, form->form_name)) {
3279 result = winreg_printer_deleteform1(tmp_ctx, session_info,
3280 msg_ctx, form_name);
3281 if (!W_ERROR_IS_OK(result)) {
3282 DEBUG(0, ("winreg_printer_setform1: Could not open key %s: %s\n",
3283 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3284 goto done;
3288 wvalue.name = form->form_name;
3290 blob = data_blob_talloc(tmp_ctx, NULL, 32);
3291 SIVAL(blob.data, 0, form->size.width);
3292 SIVAL(blob.data, 4, form->size.height);
3293 SIVAL(blob.data, 8, form->area.left);
3294 SIVAL(blob.data, 12, form->area.top);
3295 SIVAL(blob.data, 16, form->area.right);
3296 SIVAL(blob.data, 20, form->area.bottom);
3297 SIVAL(blob.data, 24, 42);
3298 SIVAL(blob.data, 28, form->flags);
3300 status = dcerpc_winreg_SetValue(winreg_handle,
3301 tmp_ctx,
3302 &key_hnd,
3303 wvalue,
3304 REG_BINARY,
3305 blob.data,
3306 blob.length,
3307 &result);
3308 if (!NT_STATUS_IS_OK(status)) {
3309 DEBUG(0, ("winreg_printer_setform1: Could not set value %s: %s\n",
3310 wvalue.name, nt_errstr(status)));
3311 result = ntstatus_to_werror(status);
3314 done:
3315 if (winreg_handle != NULL) {
3316 WERROR ignore;
3318 if (is_valid_policy_hnd(&key_hnd)) {
3319 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3321 if (is_valid_policy_hnd(&hive_hnd)) {
3322 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3326 TALLOC_FREE(tmp_ctx);
3327 return result;
3330 WERROR winreg_printer_getform1(TALLOC_CTX *mem_ctx,
3331 const struct auth_serversupplied_info *session_info,
3332 struct messaging_context *msg_ctx,
3333 const char *form_name,
3334 struct spoolss_FormInfo1 *r)
3336 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3337 struct dcerpc_binding_handle *winreg_handle = NULL;
3338 struct policy_handle hive_hnd, key_hnd;
3339 struct winreg_String wvalue;
3340 enum winreg_Type type_in = REG_NONE;
3341 uint8_t *data_in = NULL;
3342 uint32_t data_in_size = 0;
3343 uint32_t value_len = 0;
3344 uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
3345 uint32_t i;
3346 WERROR result;
3347 NTSTATUS status;
3348 TALLOC_CTX *tmp_ctx;
3350 /* check builtin forms first */
3351 for (i = 0; i < num_builtin; i++) {
3352 if (strequal(builtin_forms1[i].form_name, form_name)) {
3353 *r = builtin_forms1[i];
3354 return WERR_OK;
3358 tmp_ctx = talloc_stackframe();
3359 if (tmp_ctx == NULL) {
3360 return WERR_NOMEM;
3363 ZERO_STRUCT(hive_hnd);
3364 ZERO_STRUCT(key_hnd);
3366 result = winreg_printer_openkey(tmp_ctx,
3367 session_info,
3368 msg_ctx,
3369 &winreg_handle,
3370 TOP_LEVEL_CONTROL_FORMS_KEY,
3372 true,
3373 access_mask,
3374 &hive_hnd,
3375 &key_hnd);
3376 if (!W_ERROR_IS_OK(result)) {
3377 DEBUG(2, ("winreg_printer_getform1: Could not open key %s: %s\n",
3378 TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3379 goto done;
3382 wvalue.name = form_name;
3385 * call QueryValue once with data == NULL to get the
3386 * needed memory size to be allocated, then allocate
3387 * data buffer and call again.
3389 status = dcerpc_winreg_QueryValue(winreg_handle,
3390 tmp_ctx,
3391 &key_hnd,
3392 &wvalue,
3393 &type_in,
3394 NULL,
3395 &data_in_size,
3396 &value_len,
3397 &result);
3398 if (!NT_STATUS_IS_OK(status)) {
3399 DEBUG(0, ("winreg_printer_getform1: Could not query value %s: %s\n",
3400 wvalue.name, nt_errstr(status)));
3401 result = ntstatus_to_werror(status);
3402 goto done;
3404 if (!W_ERROR_IS_OK(result)) {
3405 goto done;
3408 data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
3409 if (data_in == NULL) {
3410 result = WERR_NOMEM;
3411 goto done;
3413 value_len = 0;
3415 status = dcerpc_winreg_QueryValue(winreg_handle,
3416 tmp_ctx,
3417 &key_hnd,
3418 &wvalue,
3419 &type_in,
3420 data_in,
3421 &data_in_size,
3422 &value_len,
3423 &result);
3424 if (!NT_STATUS_IS_OK(status)) {
3425 DEBUG(0, ("winreg_printer_getform1: Could not query value %s: %s\n",
3426 wvalue.name, nt_errstr(status)));
3427 result = ntstatus_to_werror(status);
3428 goto done;
3430 if (!W_ERROR_IS_OK(result)) {
3431 goto done;
3434 r->form_name = talloc_strdup(mem_ctx, form_name);
3435 if (r->form_name == NULL) {
3436 result = WERR_NOMEM;
3437 goto done;
3440 r->size.width = IVAL(data_in, 0);
3441 r->size.height = IVAL(data_in, 4);
3442 r->area.left = IVAL(data_in, 8);
3443 r->area.top = IVAL(data_in, 12);
3444 r->area.right = IVAL(data_in, 16);
3445 r->area.bottom = IVAL(data_in, 20);
3446 /* skip index IVAL(data_in, 24)));*/
3447 r->flags = (enum spoolss_FormFlags) IVAL(data_in, 28);
3449 result = WERR_OK;
3450 done:
3451 if (winreg_handle != NULL) {
3452 WERROR ignore;
3454 if (is_valid_policy_hnd(&key_hnd)) {
3455 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3457 if (is_valid_policy_hnd(&hive_hnd)) {
3458 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3462 TALLOC_FREE(tmp_ctx);
3463 return result;
3466 WERROR winreg_add_driver(TALLOC_CTX *mem_ctx,
3467 const struct auth_serversupplied_info *session_info,
3468 struct messaging_context *msg_ctx,
3469 struct spoolss_AddDriverInfoCtr *r,
3470 const char **driver_name,
3471 uint32_t *driver_version)
3473 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3474 struct dcerpc_binding_handle *winreg_handle = NULL;
3475 struct policy_handle hive_hnd, key_hnd;
3476 struct spoolss_DriverInfo8 info8;
3477 TALLOC_CTX *tmp_ctx = NULL;
3478 NTSTATUS status;
3479 WERROR result;
3481 ZERO_STRUCT(hive_hnd);
3482 ZERO_STRUCT(key_hnd);
3483 ZERO_STRUCT(info8);
3485 if (!driver_info_ctr_to_info8(r, &info8)) {
3486 result = WERR_INVALID_PARAMETER;
3487 goto done;
3490 tmp_ctx = talloc_stackframe();
3491 if (tmp_ctx == NULL) {
3492 return WERR_NOMEM;
3495 result = winreg_printer_opendriver(tmp_ctx,
3496 session_info,
3497 msg_ctx,
3498 info8.driver_name,
3499 info8.architecture,
3500 info8.version,
3501 access_mask, true,
3502 &winreg_handle,
3503 &hive_hnd,
3504 &key_hnd);
3505 if (!W_ERROR_IS_OK(result)) {
3506 DEBUG(0, ("winreg_add_driver: "
3507 "Could not open driver key (%s,%s,%d): %s\n",
3508 info8.driver_name, info8.architecture,
3509 info8.version, win_errstr(result)));
3510 goto done;
3513 /* TODO: "Attributes" ? */
3515 status = dcerpc_winreg_set_dword(tmp_ctx,
3516 winreg_handle,
3517 &key_hnd,
3518 "Version",
3519 info8.version,
3520 &result);
3521 if (!NT_STATUS_IS_OK(status)) {
3522 result = ntstatus_to_werror(status);
3524 if (!W_ERROR_IS_OK(result)) {
3525 goto done;
3528 status = dcerpc_winreg_set_sz(tmp_ctx,
3529 winreg_handle,
3530 &key_hnd,
3531 "Driver",
3532 info8.driver_path,
3533 &result);
3534 if (!NT_STATUS_IS_OK(status)) {
3535 result = ntstatus_to_werror(status);
3537 if (!W_ERROR_IS_OK(result)) {
3538 goto done;
3541 status = dcerpc_winreg_set_sz(tmp_ctx,
3542 winreg_handle,
3543 &key_hnd,
3544 "Data File",
3545 info8.data_file,
3546 &result);
3547 if (!NT_STATUS_IS_OK(status)) {
3548 result = ntstatus_to_werror(status);
3550 if (!W_ERROR_IS_OK(result)) {
3551 goto done;
3554 status = dcerpc_winreg_set_sz(tmp_ctx,
3555 winreg_handle,
3556 &key_hnd,
3557 "Configuration File",
3558 info8.config_file,
3559 &result);
3560 if (!NT_STATUS_IS_OK(status)) {
3561 result = ntstatus_to_werror(status);
3563 if (!W_ERROR_IS_OK(result)) {
3564 goto done;
3567 status = dcerpc_winreg_set_sz(tmp_ctx,
3568 winreg_handle,
3569 &key_hnd,
3570 "Help File",
3571 info8.help_file,
3572 &result);
3573 if (!NT_STATUS_IS_OK(status)) {
3574 result = ntstatus_to_werror(status);
3576 if (!W_ERROR_IS_OK(result)) {
3577 goto done;
3580 status = dcerpc_winreg_set_multi_sz(tmp_ctx,
3581 winreg_handle,
3582 &key_hnd,
3583 "Dependent Files",
3584 info8.dependent_files,
3585 &result);
3586 if (!NT_STATUS_IS_OK(status)) {
3587 result = ntstatus_to_werror(status);
3589 if (!W_ERROR_IS_OK(result)) {
3590 goto done;
3593 status = dcerpc_winreg_set_sz(tmp_ctx,
3594 winreg_handle,
3595 &key_hnd,
3596 "Monitor",
3597 info8.monitor_name,
3598 &result);
3599 if (!NT_STATUS_IS_OK(status)) {
3600 result = ntstatus_to_werror(status);
3602 if (!W_ERROR_IS_OK(result)) {
3603 goto done;
3606 status = dcerpc_winreg_set_sz(tmp_ctx,
3607 winreg_handle,
3608 &key_hnd,
3609 "Datatype",
3610 info8.default_datatype,
3611 &result);
3612 if (!NT_STATUS_IS_OK(status)) {
3613 result = ntstatus_to_werror(status);
3615 if (!W_ERROR_IS_OK(result)) {
3616 goto done;
3619 status = dcerpc_winreg_set_multi_sz(tmp_ctx,
3620 winreg_handle,
3621 &key_hnd, "Previous Names",
3622 info8.previous_names,
3623 &result);
3624 if (!NT_STATUS_IS_OK(status)) {
3625 result = ntstatus_to_werror(status);
3627 if (!W_ERROR_IS_OK(result)) {
3628 goto done;
3631 result = winreg_printer_write_date(tmp_ctx, winreg_handle,
3632 &key_hnd, "DriverDate",
3633 info8.driver_date);
3634 if (!W_ERROR_IS_OK(result)) {
3635 goto done;
3638 result = winreg_printer_write_ver(tmp_ctx, winreg_handle,
3639 &key_hnd, "DriverVersion",
3640 info8.driver_version);
3641 if (!W_ERROR_IS_OK(result)) {
3642 goto done;
3645 status = dcerpc_winreg_set_sz(tmp_ctx,
3646 winreg_handle,
3647 &key_hnd,
3648 "Manufacturer",
3649 info8.manufacturer_name,
3650 &result);
3651 if (!NT_STATUS_IS_OK(status)) {
3652 result = ntstatus_to_werror(status);
3654 if (!W_ERROR_IS_OK(result)) {
3655 goto done;
3658 status = dcerpc_winreg_set_sz(tmp_ctx,
3659 winreg_handle,
3660 &key_hnd,
3661 "OEM URL",
3662 info8.manufacturer_url,
3663 &result);
3664 if (!NT_STATUS_IS_OK(status)) {
3665 result = ntstatus_to_werror(status);
3667 if (!W_ERROR_IS_OK(result)) {
3668 goto done;
3671 status = dcerpc_winreg_set_sz(tmp_ctx,
3672 winreg_handle,
3673 &key_hnd,
3674 "HardwareID",
3675 info8.hardware_id,
3676 &result);
3677 if (!NT_STATUS_IS_OK(status)) {
3678 result = ntstatus_to_werror(status);
3680 if (!W_ERROR_IS_OK(result)) {
3681 goto done;
3684 status = dcerpc_winreg_set_sz(tmp_ctx,
3685 winreg_handle,
3686 &key_hnd,
3687 "Provider",
3688 info8.provider,
3689 &result);
3690 if (!NT_STATUS_IS_OK(status)) {
3691 result = ntstatus_to_werror(status);
3693 if (!W_ERROR_IS_OK(result)) {
3694 goto done;
3697 status = dcerpc_winreg_set_sz(tmp_ctx,
3698 winreg_handle,
3699 &key_hnd,
3700 "Print Processor",
3701 info8.print_processor,
3702 &result);
3703 if (!NT_STATUS_IS_OK(status)) {
3704 result = ntstatus_to_werror(status);
3706 if (!W_ERROR_IS_OK(result)) {
3707 goto done;
3710 status = dcerpc_winreg_set_sz(tmp_ctx,
3711 winreg_handle,
3712 &key_hnd,
3713 "VendorSetup",
3714 info8.vendor_setup,
3715 &result);
3716 if (!NT_STATUS_IS_OK(status)) {
3717 result = ntstatus_to_werror(status);
3719 if (!W_ERROR_IS_OK(result)) {
3720 goto done;
3723 status = dcerpc_winreg_set_multi_sz(tmp_ctx,
3724 winreg_handle,
3725 &key_hnd,
3726 "Color Profiles",
3727 info8.color_profiles,
3728 &result);
3729 if (!NT_STATUS_IS_OK(status)) {
3730 result = ntstatus_to_werror(status);
3732 if (!W_ERROR_IS_OK(result)) {
3733 goto done;
3736 status = dcerpc_winreg_set_sz(tmp_ctx,
3737 winreg_handle,
3738 &key_hnd,
3739 "InfPath",
3740 info8.inf_path,
3741 &result);
3742 if (!NT_STATUS_IS_OK(status)) {
3743 result = ntstatus_to_werror(status);
3745 if (!W_ERROR_IS_OK(result)) {
3746 goto done;
3749 status = dcerpc_winreg_set_dword(tmp_ctx,
3750 winreg_handle,
3751 &key_hnd,
3752 "PrinterDriverAttributes",
3753 info8.printer_driver_attributes,
3754 &result);
3755 if (!NT_STATUS_IS_OK(status)) {
3756 result = ntstatus_to_werror(status);
3758 if (!W_ERROR_IS_OK(result)) {
3759 goto done;
3762 status = dcerpc_winreg_set_multi_sz(tmp_ctx,
3763 winreg_handle,
3764 &key_hnd,
3765 "CoreDependencies",
3766 info8.core_driver_dependencies,
3767 &result);
3768 if (!NT_STATUS_IS_OK(status)) {
3769 result = ntstatus_to_werror(status);
3771 if (!W_ERROR_IS_OK(result)) {
3772 goto done;
3775 result = winreg_printer_write_date(tmp_ctx, winreg_handle,
3776 &key_hnd, "MinInboxDriverVerDate",
3777 info8.min_inbox_driver_ver_date);
3778 if (!W_ERROR_IS_OK(result)) {
3779 goto done;
3782 result = winreg_printer_write_ver(tmp_ctx, winreg_handle, &key_hnd,
3783 "MinInboxDriverVerVersion",
3784 info8.min_inbox_driver_ver_version);
3785 if (!W_ERROR_IS_OK(result)) {
3786 goto done;
3789 *driver_name = info8.driver_name;
3790 *driver_version = info8.version;
3791 result = WERR_OK;
3792 done:
3793 if (winreg_handle != NULL) {
3794 WERROR ignore;
3796 if (is_valid_policy_hnd(&key_hnd)) {
3797 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3799 if (is_valid_policy_hnd(&hive_hnd)) {
3800 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3804 TALLOC_FREE(tmp_ctx);
3805 return result;
3808 WERROR winreg_get_driver(TALLOC_CTX *mem_ctx,
3809 const struct auth_serversupplied_info *session_info,
3810 struct messaging_context *msg_ctx,
3811 const char *architecture,
3812 const char *driver_name,
3813 uint32_t driver_version,
3814 struct spoolss_DriverInfo8 **_info8)
3816 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3817 struct dcerpc_binding_handle *winreg_handle = NULL;
3818 struct policy_handle hive_hnd, key_hnd;
3819 struct spoolss_DriverInfo8 i8, *info8;
3820 struct spoolss_PrinterEnumValues *enum_values = NULL;
3821 struct spoolss_PrinterEnumValues *v;
3822 uint32_t num_values = 0;
3823 TALLOC_CTX *tmp_ctx;
3824 WERROR result;
3825 uint32_t i;
3827 ZERO_STRUCT(hive_hnd);
3828 ZERO_STRUCT(key_hnd);
3829 ZERO_STRUCT(i8);
3831 tmp_ctx = talloc_stackframe();
3832 if (tmp_ctx == NULL) {
3833 return WERR_NOMEM;
3836 if (driver_version == DRIVER_ANY_VERSION) {
3837 /* look for Win2k first and then for NT4 */
3838 result = winreg_printer_opendriver(tmp_ctx,
3839 session_info,
3840 msg_ctx,
3841 driver_name,
3842 architecture,
3844 access_mask, false,
3845 &winreg_handle,
3846 &hive_hnd,
3847 &key_hnd);
3848 if (!W_ERROR_IS_OK(result)) {
3849 result = winreg_printer_opendriver(tmp_ctx,
3850 session_info,
3851 msg_ctx,
3852 driver_name,
3853 architecture,
3855 access_mask, false,
3856 &winreg_handle,
3857 &hive_hnd,
3858 &key_hnd);
3860 } else {
3861 /* ok normal case */
3862 result = winreg_printer_opendriver(tmp_ctx,
3863 session_info,
3864 msg_ctx,
3865 driver_name,
3866 architecture,
3867 driver_version,
3868 access_mask, false,
3869 &winreg_handle,
3870 &hive_hnd,
3871 &key_hnd);
3873 if (!W_ERROR_IS_OK(result)) {
3874 DEBUG(5, ("winreg_get_driver: "
3875 "Could not open driver key (%s,%s,%d): %s\n",
3876 driver_name, architecture,
3877 driver_version, win_errstr(result)));
3878 goto done;
3881 result = winreg_printer_enumvalues(tmp_ctx,
3882 winreg_handle,
3883 &key_hnd,
3884 &num_values,
3885 &enum_values);
3886 if (!W_ERROR_IS_OK(result)) {
3887 DEBUG(0, ("winreg_get_driver: "
3888 "Could not enumerate values for (%s,%s,%d): %s\n",
3889 driver_name, architecture,
3890 driver_version, win_errstr(result)));
3891 goto done;
3894 info8 = talloc_zero(tmp_ctx, struct spoolss_DriverInfo8);
3895 if (info8 == NULL) {
3896 result = WERR_NOMEM;
3897 goto done;
3900 info8->driver_name = talloc_strdup(info8, driver_name);
3901 if (info8->driver_name == NULL) {
3902 result = WERR_NOMEM;
3903 goto done;
3906 info8->architecture = talloc_strdup(info8, architecture);
3907 if (info8->architecture == NULL) {
3908 result = WERR_NOMEM;
3909 goto done;
3912 result = WERR_OK;
3914 for (i = 0; i < num_values; i++) {
3915 const char *tmp_str;
3916 uint32_t tmp = 0;
3918 v = &enum_values[i];
3920 result = winreg_enumval_to_dword(info8, v,
3921 "Version",
3922 &tmp);
3923 if (NT_STATUS_IS_OK(result)) {
3924 info8->version = (enum spoolss_DriverOSVersion) tmp;
3926 CHECK_ERROR(result);
3928 result = winreg_enumval_to_sz(info8, v,
3929 "Driver",
3930 &info8->driver_path);
3931 CHECK_ERROR(result);
3933 result = winreg_enumval_to_sz(info8, v,
3934 "Data File",
3935 &info8->data_file);
3936 CHECK_ERROR(result);
3938 result = winreg_enumval_to_sz(info8, v,
3939 "Configuration File",
3940 &info8->config_file);
3941 CHECK_ERROR(result);
3943 result = winreg_enumval_to_sz(info8, v,
3944 "Help File",
3945 &info8->help_file);
3946 CHECK_ERROR(result);
3948 result = winreg_enumval_to_multi_sz(info8, v,
3949 "Dependent Files",
3950 &info8->dependent_files);
3951 CHECK_ERROR(result);
3953 result = winreg_enumval_to_sz(info8, v,
3954 "Monitor",
3955 &info8->monitor_name);
3956 CHECK_ERROR(result);
3958 result = winreg_enumval_to_sz(info8, v,
3959 "Datatype",
3960 &info8->default_datatype);
3961 CHECK_ERROR(result);
3963 result = winreg_enumval_to_multi_sz(info8, v,
3964 "Previous Names",
3965 &info8->previous_names);
3966 CHECK_ERROR(result);
3968 result = winreg_enumval_to_sz(info8, v,
3969 "DriverDate",
3970 &tmp_str);
3971 if (W_ERROR_IS_OK(result)) {
3972 result = winreg_printer_date_to_NTTIME(tmp_str,
3973 &info8->driver_date);
3975 CHECK_ERROR(result);
3977 result = winreg_enumval_to_sz(info8, v,
3978 "DriverVersion",
3979 &tmp_str);
3980 if (W_ERROR_IS_OK(result)) {
3981 result = winreg_printer_ver_to_dword(tmp_str,
3982 &info8->driver_version);
3984 CHECK_ERROR(result);
3986 result = winreg_enumval_to_sz(info8, v,
3987 "Manufacturer",
3988 &info8->manufacturer_name);
3989 CHECK_ERROR(result);
3991 result = winreg_enumval_to_sz(info8, v,
3992 "OEM URL",
3993 &info8->manufacturer_url);
3994 CHECK_ERROR(result);
3996 result = winreg_enumval_to_sz(info8, v,
3997 "HardwareID",
3998 &info8->hardware_id);
3999 CHECK_ERROR(result);
4001 result = winreg_enumval_to_sz(info8, v,
4002 "Provider",
4003 &info8->provider);
4004 CHECK_ERROR(result);
4006 result = winreg_enumval_to_sz(info8, v,
4007 "Print Processor",
4008 &info8->print_processor);
4009 CHECK_ERROR(result);
4011 result = winreg_enumval_to_sz(info8, v,
4012 "VendorSetup",
4013 &info8->vendor_setup);
4014 CHECK_ERROR(result);
4016 result = winreg_enumval_to_multi_sz(info8, v,
4017 "Color Profiles",
4018 &info8->color_profiles);
4019 CHECK_ERROR(result);
4021 result = winreg_enumval_to_sz(info8, v,
4022 "InfPath",
4023 &info8->inf_path);
4024 CHECK_ERROR(result);
4026 result = winreg_enumval_to_dword(info8, v,
4027 "PrinterDriverAttributes",
4028 &info8->printer_driver_attributes);
4029 CHECK_ERROR(result);
4031 result = winreg_enumval_to_multi_sz(info8, v,
4032 "CoreDependencies",
4033 &info8->core_driver_dependencies);
4034 CHECK_ERROR(result);
4036 result = winreg_enumval_to_sz(info8, v,
4037 "MinInboxDriverVerDate",
4038 &tmp_str);
4039 if (W_ERROR_IS_OK(result)) {
4040 result = winreg_printer_date_to_NTTIME(tmp_str,
4041 &info8->min_inbox_driver_ver_date);
4043 CHECK_ERROR(result);
4045 result = winreg_enumval_to_sz(info8, v,
4046 "MinInboxDriverVerVersion",
4047 &tmp_str);
4048 if (W_ERROR_IS_OK(result)) {
4049 result = winreg_printer_ver_to_dword(tmp_str,
4050 &info8->min_inbox_driver_ver_version);
4052 CHECK_ERROR(result);
4055 if (!W_ERROR_IS_OK(result)) {
4056 DEBUG(0, ("winreg_enumval_to_TYPE() failed "
4057 "for %s: %s\n", v->value_name,
4058 win_errstr(result)));
4059 goto done;
4062 *_info8 = talloc_steal(mem_ctx, info8);
4063 result = WERR_OK;
4064 done:
4065 if (winreg_handle != NULL) {
4066 WERROR ignore;
4068 if (is_valid_policy_hnd(&key_hnd)) {
4069 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
4071 if (is_valid_policy_hnd(&hive_hnd)) {
4072 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
4076 TALLOC_FREE(tmp_ctx);
4077 return result;
4080 WERROR winreg_del_driver(TALLOC_CTX *mem_ctx,
4081 const struct auth_serversupplied_info *session_info,
4082 struct messaging_context *msg_ctx,
4083 struct spoolss_DriverInfo8 *info8,
4084 uint32_t version)
4086 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4087 struct dcerpc_binding_handle *winreg_handle = NULL;
4088 struct policy_handle hive_hnd, key_hnd;
4089 TALLOC_CTX *tmp_ctx;
4090 char *key_name;
4091 WERROR result;
4093 ZERO_STRUCT(hive_hnd);
4094 ZERO_STRUCT(key_hnd);
4096 tmp_ctx = talloc_stackframe();
4097 if (tmp_ctx == NULL) {
4098 return WERR_NOMEM;
4101 /* test that the key exists */
4102 result = winreg_printer_opendriver(tmp_ctx,
4103 session_info,
4104 msg_ctx,
4105 info8->driver_name,
4106 info8->architecture,
4107 version,
4108 access_mask, false,
4109 &winreg_handle,
4110 &hive_hnd,
4111 &key_hnd);
4112 if (!W_ERROR_IS_OK(result)) {
4113 /* key doesn't exist */
4114 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
4115 result = WERR_OK;
4116 goto done;
4119 DEBUG(5, ("winreg_del_driver: "
4120 "Could not open driver (%s,%s,%u): %s\n",
4121 info8->driver_name, info8->architecture,
4122 version, win_errstr(result)));
4123 goto done;
4127 if (is_valid_policy_hnd(&key_hnd)) {
4128 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &result);
4131 key_name = talloc_asprintf(tmp_ctx,
4132 "%s\\Environments\\%s\\Drivers\\Version-%u\\%s",
4133 TOP_LEVEL_CONTROL_KEY,
4134 info8->architecture, version,
4135 info8->driver_name);
4136 if (key_name == NULL) {
4137 result = WERR_NOMEM;
4138 goto done;
4141 result = winreg_printer_delete_subkeys(tmp_ctx,
4142 winreg_handle,
4143 &hive_hnd,
4144 access_mask,
4145 key_name);
4146 if (!W_ERROR_IS_OK(result)) {
4147 DEBUG(0, ("winreg_del_driver: "
4148 "Could not open driver (%s,%s,%u): %s\n",
4149 info8->driver_name, info8->architecture,
4150 version, win_errstr(result)));
4151 goto done;
4154 result = WERR_OK;
4155 done:
4156 if (winreg_handle != NULL) {
4157 WERROR ignore;
4159 if (is_valid_policy_hnd(&key_hnd)) {
4160 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
4162 if (is_valid_policy_hnd(&hive_hnd)) {
4163 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
4167 TALLOC_FREE(tmp_ctx);
4168 return result;
4171 WERROR winreg_get_driver_list(TALLOC_CTX *mem_ctx,
4172 const struct auth_serversupplied_info *session_info,
4173 struct messaging_context *msg_ctx,
4174 const char *architecture,
4175 uint32_t version,
4176 uint32_t *num_drivers,
4177 const char ***drivers_p)
4179 uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4180 struct dcerpc_binding_handle *winreg_handle = NULL;
4181 struct policy_handle hive_hnd, key_hnd;
4182 const char **drivers;
4183 TALLOC_CTX *tmp_ctx;
4184 WERROR result;
4185 NTSTATUS status;
4187 *num_drivers = 0;
4188 *drivers_p = NULL;
4190 ZERO_STRUCT(hive_hnd);
4191 ZERO_STRUCT(key_hnd);
4193 tmp_ctx = talloc_stackframe();
4194 if (tmp_ctx == NULL) {
4195 return WERR_NOMEM;
4198 /* use NULL for the driver name so we open the key that is
4199 * parent of all drivers for this architecture and version */
4200 result = winreg_printer_opendriver(tmp_ctx,
4201 session_info,
4202 msg_ctx,
4203 NULL,
4204 architecture,
4205 version,
4206 access_mask, false,
4207 &winreg_handle,
4208 &hive_hnd,
4209 &key_hnd);
4210 if (!W_ERROR_IS_OK(result)) {
4211 DEBUG(5, ("winreg_get_driver_list: "
4212 "Could not open key (%s,%u): %s\n",
4213 architecture, version, win_errstr(result)));
4214 result = WERR_OK;
4215 goto done;
4218 status = dcerpc_winreg_enum_keys(tmp_ctx,
4219 winreg_handle,
4220 &key_hnd,
4221 num_drivers,
4222 &drivers,
4223 &result);
4224 if (!NT_STATUS_IS_OK(status)) {
4225 result = ntstatus_to_werror(status);
4227 if (!W_ERROR_IS_OK(result)) {
4228 DEBUG(0, ("winreg_get_driver_list: "
4229 "Could not enumerate drivers for (%s,%u): %s\n",
4230 architecture, version, win_errstr(result)));
4231 goto done;
4234 *drivers_p = talloc_steal(mem_ctx, drivers);
4236 result = WERR_OK;
4237 done:
4238 if (winreg_handle != NULL) {
4239 WERROR ignore;
4241 if (is_valid_policy_hnd(&key_hnd)) {
4242 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
4244 if (is_valid_policy_hnd(&hive_hnd)) {
4245 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
4249 TALLOC_FREE(tmp_ctx);
4250 return result;