s3-spoolss: Added a sharename arg to winreg_update_printer.
[sfrench/samba-autobuild/.git] / source3 / rpc_server / srv_spoolss_util.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *
4  *  SPOOLSS RPC Pipe server / winreg client routines
5  *
6  *  Copyright (c) 2010      Andreas Schneider <asn@samba.org>
7  *
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.
12  *
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.
17  *
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/>.
20  */
21
22 #include "includes.h"
23 #include "srv_spoolss_util.h"
24 #include "../librpc/gen_ndr/srv_winreg.h"
25 #include "../librpc/gen_ndr/cli_winreg.h"
26
27 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
28 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
29 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
30 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
31
32 #define EMPTY_STRING ""
33
34 #define CHECK_ERROR(result) \
35         if (W_ERROR_IS_OK(result)) continue; \
36         if (W_ERROR_EQUAL(result, WERR_NOT_FOUND)) result = WERR_OK; \
37         if (!W_ERROR_IS_OK(result)) break
38
39 /*        FLAGS,                NAME,                              with,   height,   left, top, right, bottom */
40 static const struct spoolss_FormInfo1 builtin_forms1[] = {
41         { SPOOLSS_FORM_BUILTIN, "Letter",                         {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
42         { SPOOLSS_FORM_BUILTIN, "Letter Small",                   {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
43         { SPOOLSS_FORM_BUILTIN, "Tabloid",                        {0x44368,0x696b8}, {0x0,0x0,0x44368,0x696b8} },
44         { SPOOLSS_FORM_BUILTIN, "Ledger",                         {0x696b8,0x44368}, {0x0,0x0,0x696b8,0x44368} },
45         { SPOOLSS_FORM_BUILTIN, "Legal",                          {0x34b5c,0x56d10}, {0x0,0x0,0x34b5c,0x56d10} },
46         { SPOOLSS_FORM_BUILTIN, "Statement",                      {0x221b4,0x34b5c}, {0x0,0x0,0x221b4,0x34b5c} },
47         { SPOOLSS_FORM_BUILTIN, "Executive",                      {0x2cf56,0x411cc}, {0x0,0x0,0x2cf56,0x411cc} },
48         { SPOOLSS_FORM_BUILTIN, "A3",                             {0x48828,0x668a0}, {0x0,0x0,0x48828,0x668a0} },
49         { SPOOLSS_FORM_BUILTIN, "A4",                             {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
50         { SPOOLSS_FORM_BUILTIN, "A4 Small",                       {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
51         { SPOOLSS_FORM_BUILTIN, "A5",                             {0x24220,0x33450}, {0x0,0x0,0x24220,0x33450} },
52         { SPOOLSS_FORM_BUILTIN, "B4 (JIS)",                       {0x3ebe8,0x58de0}, {0x0,0x0,0x3ebe8,0x58de0} },
53         { SPOOLSS_FORM_BUILTIN, "B5 (JIS)",                       {0x2c6f0,0x3ebe8}, {0x0,0x0,0x2c6f0,0x3ebe8} },
54         { SPOOLSS_FORM_BUILTIN, "Folio",                          {0x34b5c,0x509d8}, {0x0,0x0,0x34b5c,0x509d8} },
55         { SPOOLSS_FORM_BUILTIN, "Quarto",                         {0x347d8,0x43238}, {0x0,0x0,0x347d8,0x43238} },
56         { SPOOLSS_FORM_BUILTIN, "10x14",                          {0x3e030,0x56d10}, {0x0,0x0,0x3e030,0x56d10} },
57         { SPOOLSS_FORM_BUILTIN, "11x17",                          {0x44368,0x696b8}, {0x0,0x0,0x44368,0x696b8} },
58         { SPOOLSS_FORM_BUILTIN, "Note",                           {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
59         { SPOOLSS_FORM_BUILTIN, "Envelope #9",                    {0x18079,0x37091}, {0x0,0x0,0x18079,0x37091} },
60         { SPOOLSS_FORM_BUILTIN, "Envelope #10",                   {0x19947,0x3ae94}, {0x0,0x0,0x19947,0x3ae94} },
61         { SPOOLSS_FORM_BUILTIN, "Envelope #11",                   {0x1be7c,0x40565}, {0x0,0x0,0x1be7c,0x40565} },
62         { SPOOLSS_FORM_BUILTIN, "Envelope #12",                   {0x1d74a,0x44368}, {0x0,0x0,0x1d74a,0x44368} },
63         { SPOOLSS_FORM_BUILTIN, "Envelope #14",                   {0x1f018,0x47504}, {0x0,0x0,0x1f018,0x47504} },
64         { SPOOLSS_FORM_BUILTIN, "C size sheet",                   {0x696b8,0x886d0}, {0x0,0x0,0x696b8,0x886d0} },
65         { SPOOLSS_FORM_BUILTIN, "D size sheet",                   {0x886d0,0xd2d70}, {0x0,0x0,0x886d0,0xd2d70} },
66         { SPOOLSS_FORM_BUILTIN, "E size sheet",                   {0xd2d70,0x110da0},{0x0,0x0,0xd2d70,0x110da0} },
67         { SPOOLSS_FORM_BUILTIN, "Envelope DL",                    {0x1adb0,0x35b60}, {0x0,0x0,0x1adb0,0x35b60} },
68         { SPOOLSS_FORM_BUILTIN, "Envelope C5",                    {0x278d0,0x37e88}, {0x0,0x0,0x278d0,0x37e88} },
69         { SPOOLSS_FORM_BUILTIN, "Envelope C3",                    {0x4f1a0,0x6fd10}, {0x0,0x0,0x4f1a0,0x6fd10} },
70         { SPOOLSS_FORM_BUILTIN, "Envelope C4",                    {0x37e88,0x4f1a0}, {0x0,0x0,0x37e88,0x4f1a0} },
71         { SPOOLSS_FORM_BUILTIN, "Envelope C6",                    {0x1bd50,0x278d0}, {0x0,0x0,0x1bd50,0x278d0} },
72         { SPOOLSS_FORM_BUILTIN, "Envelope C65",                   {0x1bd50,0x37e88}, {0x0,0x0,0x1bd50,0x37e88} },
73         { SPOOLSS_FORM_BUILTIN, "Envelope B4",                    {0x3d090,0x562e8}, {0x0,0x0,0x3d090,0x562e8} },
74         { SPOOLSS_FORM_BUILTIN, "Envelope B5",                    {0x2af80,0x3d090}, {0x0,0x0,0x2af80,0x3d090} },
75         { SPOOLSS_FORM_BUILTIN, "Envelope B6",                    {0x2af80,0x1e848}, {0x0,0x0,0x2af80,0x1e848} },
76         { SPOOLSS_FORM_BUILTIN, "Envelope",                       {0x1adb0,0x38270}, {0x0,0x0,0x1adb0,0x38270} },
77         { SPOOLSS_FORM_BUILTIN, "Envelope Monarch",               {0x18079,0x2e824}, {0x0,0x0,0x18079,0x2e824} },
78         { SPOOLSS_FORM_BUILTIN, "6 3/4 Envelope",                 {0x167ab,0x284ec}, {0x0,0x0,0x167ab,0x284ec} },
79         { SPOOLSS_FORM_BUILTIN, "US Std Fanfold",                 {0x5c3e1,0x44368}, {0x0,0x0,0x5c3e1,0x44368} },
80         { SPOOLSS_FORM_BUILTIN, "German Std Fanfold",             {0x34b5c,0x4a6a0}, {0x0,0x0,0x34b5c,0x4a6a0} },
81         { SPOOLSS_FORM_BUILTIN, "German Legal Fanfold",           {0x34b5c,0x509d8}, {0x0,0x0,0x34b5c,0x509d8} },
82         { SPOOLSS_FORM_BUILTIN, "B4 (ISO)",                       {0x3d090,0x562e8}, {0x0,0x0,0x3d090,0x562e8} },
83         { SPOOLSS_FORM_BUILTIN, "Japanese Postcard",              {0x186a0,0x24220}, {0x0,0x0,0x186a0,0x24220} },
84         { SPOOLSS_FORM_BUILTIN, "9x11",                           {0x37cf8,0x44368}, {0x0,0x0,0x37cf8,0x44368} },
85         { SPOOLSS_FORM_BUILTIN, "10x11",                          {0x3e030,0x44368}, {0x0,0x0,0x3e030,0x44368} },
86         { SPOOLSS_FORM_BUILTIN, "15x11",                          {0x5d048,0x44368}, {0x0,0x0,0x5d048,0x44368} },
87         { SPOOLSS_FORM_BUILTIN, "Envelope Invite",                {0x35b60,0x35b60}, {0x0,0x0,0x35b60,0x35b60} },
88         { SPOOLSS_FORM_BUILTIN, "Reserved48",                     {0x1,0x1},         {0x0,0x0,0x1,0x1} },
89         { SPOOLSS_FORM_BUILTIN, "Reserved49",                     {0x1,0x1},         {0x0,0x0,0x1,0x1} },
90         { SPOOLSS_FORM_BUILTIN, "Letter Extra",                   {0x3ae94,0x4a6a0}, {0x0,0x0,0x3ae94,0x4a6a0} },
91         { SPOOLSS_FORM_BUILTIN, "Legal Extra",                    {0x3ae94,0x5d048}, {0x0,0x0,0x3ae94,0x5d048} },
92         { SPOOLSS_FORM_BUILTIN, "Tabloid Extra",                  {0x4a6a0,0x6f9f0}, {0x0,0x0,0x4a6a0,0x6f9f0} },
93         { SPOOLSS_FORM_BUILTIN, "A4 Extra",                       {0x397c2,0x4eb16}, {0x0,0x0,0x397c2,0x4eb16} },
94         { SPOOLSS_FORM_BUILTIN, "Letter Transverse",              {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
95         { SPOOLSS_FORM_BUILTIN, "A4 Transverse",                  {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
96         { SPOOLSS_FORM_BUILTIN, "Letter Extra Transverse",        {0x3ae94,0x4a6a0}, {0x0,0x0,0x3ae94,0x4a6a0} },
97         { SPOOLSS_FORM_BUILTIN, "Super A",                        {0x376b8,0x56ea0}, {0x0,0x0,0x376b8,0x56ea0} },
98         { SPOOLSS_FORM_BUILTIN, "Super B",                        {0x4a768,0x76e58}, {0x0,0x0,0x4a768,0x76e58} },
99         { SPOOLSS_FORM_BUILTIN, "Letter Plus",                    {0x34b5c,0x4eb16}, {0x0,0x0,0x34b5c,0x4eb16} },
100         { SPOOLSS_FORM_BUILTIN, "A4 Plus",                        {0x33450,0x50910}, {0x0,0x0,0x33450,0x50910} },
101         { SPOOLSS_FORM_BUILTIN, "A5 Transverse",                  {0x24220,0x33450}, {0x0,0x0,0x24220,0x33450} },
102         { SPOOLSS_FORM_BUILTIN, "B5 (JIS) Transverse",            {0x2c6f0,0x3ebe8}, {0x0,0x0,0x2c6f0,0x3ebe8} },
103         { SPOOLSS_FORM_BUILTIN, "A3 Extra",                       {0x4e9d0,0x6ca48}, {0x0,0x0,0x4e9d0,0x6ca48} },
104         { SPOOLSS_FORM_BUILTIN, "A5 Extra",                       {0x2a7b0,0x395f8}, {0x0,0x0,0x2a7b0,0x395f8} },
105         { SPOOLSS_FORM_BUILTIN, "B5 (ISO) Extra",                 {0x31128,0x43620}, {0x0,0x0,0x31128,0x43620} },
106         { SPOOLSS_FORM_BUILTIN, "A2",                             {0x668a0,0x91050}, {0x0,0x0,0x668a0,0x91050} },
107         { SPOOLSS_FORM_BUILTIN, "A3 Transverse",                  {0x48828,0x668a0}, {0x0,0x0,0x48828,0x668a0} },
108         { SPOOLSS_FORM_BUILTIN, "A3 Extra Transverse",            {0x4e9d0,0x6ca48}, {0x0,0x0,0x4e9d0,0x6ca48} },
109         { SPOOLSS_FORM_BUILTIN, "Japanese Double Postcard",       {0x30d40,0x24220}, {0x0,0x0,0x30d40,0x24220} },
110         { SPOOLSS_FORM_BUILTIN, "A6",                             {0x19a28,0x24220}, {0x0,0x0,0x19a28,0x24220} },
111         { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Kaku #2",      {0x3a980,0x510e0}, {0x0,0x0,0x3a980,0x510e0} },
112         { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Kaku #3",      {0x34bc0,0x43a08}, {0x0,0x0,0x34bc0,0x43a08} },
113         { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Chou #3",      {0x1d4c0,0x395f8}, {0x0,0x0,0x1d4c0,0x395f8} },
114         { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Chou #4",      {0x15f90,0x320c8}, {0x0,0x0,0x15f90,0x320c8} },
115         { SPOOLSS_FORM_BUILTIN, "Letter Rotated",                 {0x44368,0x34b5c}, {0x0,0x0,0x44368,0x34b5c} },
116         { SPOOLSS_FORM_BUILTIN, "A3 Rotated",                     {0x668a0,0x48828}, {0x0,0x0,0x668a0,0x48828} },
117         { SPOOLSS_FORM_BUILTIN, "A4 Rotated",                     {0x48828,0x33450}, {0x0,0x0,0x48828,0x33450} },
118         { SPOOLSS_FORM_BUILTIN, "A5 Rotated",                     {0x33450,0x24220}, {0x0,0x0,0x33450,0x24220} },
119         { SPOOLSS_FORM_BUILTIN, "B4 (JIS) Rotated",               {0x58de0,0x3ebe8}, {0x0,0x0,0x58de0,0x3ebe8} },
120         { SPOOLSS_FORM_BUILTIN, "B5 (JIS) Rotated",               {0x3ebe8,0x2c6f0}, {0x0,0x0,0x3ebe8,0x2c6f0} },
121         { SPOOLSS_FORM_BUILTIN, "Japanese Postcard Rotated",      {0x24220,0x186a0}, {0x0,0x0,0x24220,0x186a0} },
122         { SPOOLSS_FORM_BUILTIN, "Double Japan Postcard Rotated",  {0x24220,0x30d40}, {0x0,0x0,0x24220,0x30d40} },
123         { SPOOLSS_FORM_BUILTIN, "A6 Rotated",                     {0x24220,0x19a28}, {0x0,0x0,0x24220,0x19a28} },
124         { SPOOLSS_FORM_BUILTIN, "Japan Envelope Kaku #2 Rotated", {0x510e0,0x3a980}, {0x0,0x0,0x510e0,0x3a980} },
125         { SPOOLSS_FORM_BUILTIN, "Japan Envelope Kaku #3 Rotated", {0x43a08,0x34bc0}, {0x0,0x0,0x43a08,0x34bc0} },
126         { SPOOLSS_FORM_BUILTIN, "Japan Envelope Chou #3 Rotated", {0x395f8,0x1d4c0}, {0x0,0x0,0x395f8,0x1d4c0} },
127         { SPOOLSS_FORM_BUILTIN, "Japan Envelope Chou #4 Rotated", {0x320c8,0x15f90}, {0x0,0x0,0x320c8,0x15f90} },
128         { SPOOLSS_FORM_BUILTIN, "B6 (JIS)",                       {0x1f400,0x2c6f0}, {0x0,0x0,0x1f400,0x2c6f0} },
129         { SPOOLSS_FORM_BUILTIN, "B6 (JIS) Rotated",               {0x2c6f0,0x1f400}, {0x0,0x0,0x2c6f0,0x1f400} },
130         { SPOOLSS_FORM_BUILTIN, "12x11",                          {0x4a724,0x443e1}, {0x0,0x0,0x4a724,0x443e1} },
131         { SPOOLSS_FORM_BUILTIN, "Japan Envelope You #4",          {0x19a28,0x395f8}, {0x0,0x0,0x19a28,0x395f8} },
132         { SPOOLSS_FORM_BUILTIN, "Japan Envelope You #4 Rotated",  {0x395f8,0x19a28}, {0x0,0x0,0x395f8,0x19a28} },
133         { SPOOLSS_FORM_BUILTIN, "PRC 16K",                        {0x2de60,0x3f7a0}, {0x0,0x0,0x2de60,0x3f7a0} },
134         { SPOOLSS_FORM_BUILTIN, "PRC 32K",                        {0x1fbd0,0x2cec0}, {0x0,0x0,0x1fbd0,0x2cec0} },
135         { SPOOLSS_FORM_BUILTIN, "PRC 32K(Big)",                   {0x222e0,0x318f8}, {0x0,0x0,0x222e0,0x318f8} },
136         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #1",                {0x18e70,0x28488}, {0x0,0x0,0x18e70,0x28488} },
137         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #2",                {0x18e70,0x2af80}, {0x0,0x0,0x18e70,0x2af80} },
138         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #3",                {0x1e848,0x2af80}, {0x0,0x0,0x1e848,0x2af80} },
139         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #4",                {0x1adb0,0x32c80}, {0x0,0x0,0x1adb0,0x32c80} },
140         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #5",                {0x1adb0,0x35b60}, {0x0,0x0,0x1adb0,0x35b60} },
141         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #6",                {0x1d4c0,0x38270}, {0x0,0x0,0x1d4c0,0x38270} },
142         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #7",                {0x27100,0x38270}, {0x0,0x0,0x27100,0x38270} },
143         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #8",                {0x1d4c0,0x4b708}, {0x0,0x0,0x1d4c0,0x4b708} },
144         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #9",                {0x37e88,0x4f1a0}, {0x0,0x0,0x37e88,0x4f1a0} },
145         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #10",               {0x4f1a0,0x6fd10}, {0x0,0x0,0x4f1a0,0x6fd10} },
146         { SPOOLSS_FORM_BUILTIN, "PRC 16K Rotated",                {0x3f7a0,0x2de60}, {0x0,0x0,0x3f7a0,0x2de60} },
147         { SPOOLSS_FORM_BUILTIN, "PRC 32K Rotated",                {0x2cec0,0x1fbd0}, {0x0,0x0,0x2cec0,0x1fbd0} },
148         { SPOOLSS_FORM_BUILTIN, "PRC 32K(Big) Rotated",           {0x318f8,0x222e0}, {0x0,0x0,0x318f8,0x222e0} },
149         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #1 Rotated",        {0x28488,0x18e70}, {0x0,0x0,0x28488,0x18e70} },
150         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #2 Rotated",        {0x2af80,0x18e70}, {0x0,0x0,0x2af80,0x18e70} },
151         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #3 Rotated",        {0x2af80,0x1e848}, {0x0,0x0,0x2af80,0x1e848} },
152         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #4 Rotated",        {0x32c80,0x1adb0}, {0x0,0x0,0x32c80,0x1adb0} },
153         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #5 Rotated",        {0x35b60,0x1adb0}, {0x0,0x0,0x35b60,0x1adb0} },
154         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #6 Rotated",        {0x38270,0x1d4c0}, {0x0,0x0,0x38270,0x1d4c0} },
155         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #7 Rotated",        {0x38270,0x27100}, {0x0,0x0,0x38270,0x27100} },
156         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #8 Rotated",        {0x4b708,0x1d4c0}, {0x0,0x0,0x4b708,0x1d4c0} },
157         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #9 Rotated",        {0x4f1a0,0x37e88}, {0x0,0x0,0x4f1a0,0x37e88} },
158         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #10 Rotated",       {0x6fd10,0x4f1a0}, {0x0,0x0,0x6fd10,0x4f1a0} }
159 };
160
161 /********************************************************************
162  static helper functions
163 ********************************************************************/
164
165 /****************************************************************************
166  Update the changeid time.
167 ****************************************************************************/
168 /**
169  * @internal
170  *
171  * @brief Update the ChangeID time of a printer.
172  *
173  * This is SO NASTY as some drivers need this to change, others need it
174  * static. This value will change every second, and I must hope that this
175  * is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
176  * UTAH ! JRA.
177  *
178  * @return              The ChangeID.
179  */
180 static uint32_t winreg_printer_rev_changeid(void)
181 {
182         struct timeval tv;
183
184         get_process_uptime(&tv);
185
186 #if 1   /* JERRY */
187         /* Return changeid as msec since spooler restart */
188         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
189 #else
190         /*
191          * This setting seems to work well but is too untested
192          * to replace the above calculation.  Left in for experiementation
193          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
194          */
195         return tv.tv_sec * 10 + tv.tv_usec / 100000;
196 #endif
197 }
198
199 static struct spoolss_security_descriptor *winreg_printer_create_default_secdesc(TALLOC_CTX *ctx)
200 {
201         SEC_ACE ace[5]; /* max number of ace entries */
202         int i = 0;
203         uint32_t sa;
204         SEC_ACL *psa = NULL;
205         SEC_DESC *psd = NULL;
206         DOM_SID adm_sid;
207         size_t sd_size;
208
209         /* Create an ACE where Everyone is allowed to print */
210
211         sa = PRINTER_ACE_PRINT;
212         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
213                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
214
215         /* Add the domain admins group if we are a DC */
216
217         if ( IS_DC ) {
218                 DOM_SID domadmins_sid;
219
220                 sid_compose(&domadmins_sid, get_global_sam_sid(),
221                             DOMAIN_GROUP_RID_ADMINS);
222
223                 sa = PRINTER_ACE_FULL_CONTROL;
224                 init_sec_ace(&ace[i++], &domadmins_sid,
225                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
226                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
227                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
228                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
229         }
230         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
231                 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
232
233                 sa = PRINTER_ACE_FULL_CONTROL;
234                 init_sec_ace(&ace[i++], &adm_sid,
235                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
236                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
237                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
238                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
239         }
240
241         /* add BUILTIN\Administrators as FULL CONTROL */
242
243         sa = PRINTER_ACE_FULL_CONTROL;
244         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
245                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
246                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
247         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
248                 SEC_ACE_TYPE_ACCESS_ALLOWED,
249                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
250
251         /* Make the security descriptor owned by the BUILTIN\Administrators */
252
253         /* The ACL revision number in rpc_secdesc.h differs from the one
254            created by NT when setting ACE entries in printer
255            descriptors.  NT4 complains about the property being edited by a
256            NT5 machine. */
257
258         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
259                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
260                         &global_sid_Builtin_Administrators,
261                         &global_sid_Builtin_Administrators,
262                         NULL, psa, &sd_size);
263         }
264
265         if (!psd) {
266                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
267                 return NULL;
268         }
269
270         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
271                  (unsigned int)sd_size));
272
273         return psd;
274 }
275
276 static struct spoolss_DeviceMode *winreg_printer_create_default_devmode(TALLOC_CTX *mem_ctx,
277                 const char *default_devicename)
278 {
279         char adevice[MAXDEVICENAME];
280         struct spoolss_DeviceMode *devmode;
281
282         devmode = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
283         if (devmode == NULL) {
284                 return NULL;
285         }
286
287         slprintf(adevice, sizeof(adevice), "%s", default_devicename);
288         devmode->devicename = talloc_strdup(mem_ctx, adevice);
289         if (devmode->devicename == NULL) {
290                 return NULL;
291         }
292
293         devmode->formname = "Letter";
294
295         devmode->specversion          = DMSPEC_NT4_AND_ABOVE;
296         devmode->driverversion        = 0x0400;
297         devmode->size                 = 0x00DC;
298         devmode->__driverextra_length = 0;
299         devmode->fields               = DEVMODE_FORMNAME |
300                                         DEVMODE_TTOPTION |
301                                         DEVMODE_PRINTQUALITY |
302                                         DEVMODE_DEFAULTSOURCE |
303                                         DEVMODE_COPIES |
304                                         DEVMODE_SCALE |
305                                         DEVMODE_PAPERSIZE |
306                                         DEVMODE_ORIENTATION;
307         devmode->orientation          = DMORIENT_PORTRAIT;
308         devmode->papersize            = DMPAPER_LETTER;
309         devmode->paperlength          = 0;
310         devmode->paperwidth           = 0;
311         devmode->scale                = 0x64;
312         devmode->copies               = 1;
313         devmode->defaultsource        = DMBIN_FORMSOURCE;
314         devmode->printquality         = DMRES_HIGH;           /* 0x0258 */
315         devmode->color                = DMRES_MONOCHROME;
316         devmode->duplex               = DMDUP_SIMPLEX;
317         devmode->yresolution          = 0;
318         devmode->ttoption             = DMTT_SUBDEV;
319         devmode->collate              = DMCOLLATE_FALSE;
320         devmode->icmmethod            = 0;
321         devmode->icmintent            = 0;
322         devmode->mediatype            = 0;
323         devmode->dithertype           = 0;
324
325         devmode->logpixels            = 0;
326         devmode->bitsperpel           = 0;
327         devmode->pelswidth            = 0;
328         devmode->pelsheight           = 0;
329         devmode->displayflags         = 0;
330         devmode->displayfrequency     = 0;
331         devmode->reserved1            = 0;
332         devmode->reserved2            = 0;
333         devmode->panningwidth         = 0;
334         devmode->panningheight        = 0;
335
336         devmode->driverextra_data.data = NULL;
337         devmode->driverextra_data.length = 0;
338
339         return devmode;
340 }
341
342 /**
343  * @internal
344  *
345  * @brief Connect to the interal winreg server and open the given printer key.
346  *
347  * The function will create the needed subkeys if they don't exist.
348  *
349  * @param[in]  mem_ctx       The memory context to use.
350  *
351  * @param[in]  server_info   The supplied server info.
352  *
353  * @param[out] winreg_pipe   A pointer for the winreg rpc client pipe.
354  *
355  * @param[in]  path          The path to the key to open.
356  *
357  * @param[in]  key           The key to open.
358  *
359  * @param[in]  create_key    Set to true if the key should be created if it
360  *                           doesn't exist.
361  *
362  * @param[in]  access_mask   The access mask to open the key.
363  *
364  * @param[out] hive_handle   A policy handle for the opened hive.
365  *
366  * @param[out] key_handle    A policy handle for the opened key.
367  *
368  * @return                   WERR_OK on success, the corresponding DOS error
369  *                           code if something gone wrong.
370  */
371 static WERROR winreg_printer_openkey(TALLOC_CTX *mem_ctx,
372                               struct auth_serversupplied_info *server_info,
373                               struct rpc_pipe_client **winreg_pipe,
374                               const char *path,
375                               const char *key,
376                               bool create_key,
377                               uint32_t access_mask,
378                               struct policy_handle *hive_handle,
379                               struct policy_handle *key_handle)
380 {
381         struct rpc_pipe_client *pipe_handle;
382         struct winreg_String wkey, wkeyclass;
383         char *keyname;
384         NTSTATUS status;
385         WERROR result = WERR_OK;
386
387         /* create winreg connection */
388         status = rpc_pipe_open_internal(mem_ctx,
389                                         &ndr_table_winreg.syntax_id,
390                                         rpc_winreg_dispatch,
391                                         server_info,
392                                         &pipe_handle);
393         if (!NT_STATUS_IS_OK(status)) {
394                 DEBUG(0, ("winreg_printer_openkey: Could not connect to winreg_pipe: %s\n",
395                           nt_errstr(status)));
396                 return ntstatus_to_werror(status);
397         }
398
399         status = rpccli_winreg_OpenHKLM(pipe_handle,
400                                         mem_ctx,
401                                         NULL,
402                                         access_mask,
403                                         hive_handle,
404                                         &result);
405         if (!NT_STATUS_IS_OK(status)) {
406                 DEBUG(0, ("winreg_printer_openkey: Could not open HKLM hive: %s\n",
407                           nt_errstr(status)));
408                 talloc_free(pipe_handle);
409                 if (!W_ERROR_IS_OK(result)) {
410                         return result;
411                 }
412                 return ntstatus_to_werror(status);
413         }
414
415         if (key && *key) {
416                 keyname = talloc_asprintf(mem_ctx, "%s\\%s", path, key);
417         } else {
418                 keyname = talloc_strdup(mem_ctx, path);
419         }
420         if (keyname == NULL) {
421                 talloc_free(pipe_handle);
422                 return WERR_NOMEM;
423         }
424
425         ZERO_STRUCT(wkey);
426         wkey.name = keyname;
427
428         if (create_key) {
429                 enum winreg_CreateAction action = REG_ACTION_NONE;
430
431                 ZERO_STRUCT(wkeyclass);
432                 wkeyclass.name = "";
433
434                 status = rpccli_winreg_CreateKey(pipe_handle,
435                                                  mem_ctx,
436                                                  hive_handle,
437                                                  wkey,
438                                                  wkeyclass,
439                                                  0,
440                                                  access_mask,
441                                                  NULL,
442                                                  key_handle,
443                                                  &action,
444                                                  &result);
445                 switch (action) {
446                         case REG_ACTION_NONE:
447                                 DEBUG(8, ("winreg_printer_openkey:createkey did nothing -- huh?\n"));
448                                 break;
449                         case REG_CREATED_NEW_KEY:
450                                 DEBUG(8, ("winreg_printer_openkey: createkey created %s\n", keyname));
451                                 break;
452                         case REG_OPENED_EXISTING_KEY:
453                                 DEBUG(8, ("winreg_printer_openkey: createkey opened existing %s\n", keyname));
454                                 break;
455                 }
456         } else {
457                 status = rpccli_winreg_OpenKey(pipe_handle,
458                                                mem_ctx,
459                                                hive_handle,
460                                                wkey,
461                                                0,
462                                                access_mask,
463                                                key_handle,
464                                                &result);
465         }
466         if (!NT_STATUS_IS_OK(status)) {
467                 talloc_free(pipe_handle);
468                 if (!W_ERROR_IS_OK(result)) {
469                         return result;
470                 }
471                 return ntstatus_to_werror(status);
472         }
473
474         *winreg_pipe = pipe_handle;
475
476         return WERR_OK;
477 }
478
479 /**
480  * @brief Create the registry keyname for the given printer.
481  *
482  * @param[in]  mem_ctx  The memory context to use.
483  *
484  * @param[in]  printer  The name of the printer to get the registry key.
485  *
486  * @return     The registry key or NULL on error.
487  */
488 static char *winreg_printer_data_keyname(TALLOC_CTX *mem_ctx, const char *printer) {
489         return talloc_asprintf(mem_ctx, "%s\\%s", TOP_LEVEL_PRINT_PRINTERS_KEY, printer);
490 }
491
492 /**
493  * @internal
494  *
495  * @brief Enumerate values of an opened key handle and retrieve the data.
496  *
497  * @param[in]  mem_ctx  The memory context to use.
498  *
499  * @param[in]  pipe_handle The pipe handle for the rpc connection.
500  *
501  * @param[in]  key_hnd  The opened key handle.
502  *
503  * @param[out] pnum_values A pointer to store he number of values found.
504  *
505  * @param[out] pnum_values A pointer to store the number of values we found.
506  *
507  * @return                   WERR_OK on success, the corresponding DOS error
508  *                           code if something gone wrong.
509  */
510 static WERROR winreg_printer_enumvalues(TALLOC_CTX *mem_ctx,
511                                         struct rpc_pipe_client *pipe_handle,
512                                         struct policy_handle *key_hnd,
513                                         uint32_t *pnum_values,
514                                         struct spoolss_PrinterEnumValues **penum_values)
515 {
516         TALLOC_CTX *tmp_ctx;
517         uint32_t num_subkeys, max_subkeylen, max_classlen;
518         uint32_t num_values, max_valnamelen, max_valbufsize;
519         uint32_t secdescsize;
520         uint32_t i;
521         NTTIME last_changed_time;
522         struct winreg_String classname;
523
524         struct spoolss_PrinterEnumValues *enum_values;
525
526         WERROR result = WERR_OK;
527         NTSTATUS status;
528
529         tmp_ctx = talloc_new(mem_ctx);
530         if (tmp_ctx == NULL) {
531                 return WERR_NOMEM;
532         }
533
534         ZERO_STRUCT(classname);
535
536         status = rpccli_winreg_QueryInfoKey(pipe_handle,
537                                             tmp_ctx,
538                                             key_hnd,
539                                             &classname,
540                                             &num_subkeys,
541                                             &max_subkeylen,
542                                             &max_classlen,
543                                             &num_values,
544                                             &max_valnamelen,
545                                             &max_valbufsize,
546                                             &secdescsize,
547                                             &last_changed_time,
548                                             &result);
549         if (!NT_STATUS_IS_OK(status)) {
550                 DEBUG(0, ("winreg_printer_enumvalues: Could not query info: %s\n",
551                           nt_errstr(status)));
552                 if (!W_ERROR_IS_OK(result)) {
553                         goto error;
554                 }
555                 result = ntstatus_to_werror(status);
556                 goto error;
557         }
558
559         if (num_values == 0) {
560                 *pnum_values = 0;
561                 TALLOC_FREE(tmp_ctx);
562                 return WERR_OK;
563         }
564
565         enum_values = TALLOC_ARRAY(tmp_ctx, struct spoolss_PrinterEnumValues, num_values);
566         if (enum_values == NULL) {
567                 result = WERR_NOMEM;
568                 goto error;
569         }
570
571         for (i = 0; i < num_values; i++) {
572                 struct spoolss_PrinterEnumValues val;
573                 struct winreg_ValNameBuf name_buf;
574                 enum winreg_Type type = REG_NONE;
575                 uint8_t *data = NULL;
576                 uint32_t data_size;
577                 uint32_t length;
578                 char n = '\0';;
579
580                 name_buf.name = &n;
581                 name_buf.size = max_valnamelen + 2;
582                 name_buf.length = 0;
583
584                 data_size = max_valbufsize;
585                 data = (uint8_t *) TALLOC(tmp_ctx, data_size);
586                 length = 0;
587
588                 status = rpccli_winreg_EnumValue(pipe_handle,
589                                                  tmp_ctx,
590                                                  key_hnd,
591                                                  i,
592                                                  &name_buf,
593                                                  &type,
594                                                  data,
595                                                  &data_size,
596                                                  &length,
597                                                  &result);
598                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
599                         result = WERR_OK;
600                         status = NT_STATUS_OK;
601                         break;
602                 }
603
604                 if (!NT_STATUS_IS_OK(status)) {
605                         DEBUG(0, ("winreg_printer_enumvalues: Could not enumerate values: %s\n",
606                                   nt_errstr(status)));
607                         if (!W_ERROR_IS_OK(result)) {
608                                 goto error;
609                         }
610                         result = ntstatus_to_werror(status);
611                         goto error;
612                 }
613
614                 if (name_buf.name == NULL) {
615                         result = WERR_INVALID_PARAMETER;
616                         goto error;
617                 }
618
619                 val.value_name = talloc_strdup(enum_values, name_buf.name);
620                 if (val.value_name == NULL) {
621                         result = WERR_NOMEM;
622                         goto error;
623                 }
624                 val.value_name_len = strlen_m_term(val.value_name) * 2;
625
626                 val.type = type;
627                 val.data_length = data_size;
628                 val.data = NULL;
629                 if (val.data_length) {
630                         val.data = talloc(enum_values, DATA_BLOB);
631                         if (val.data == NULL) {
632                                 result = WERR_NOMEM;
633                                 goto error;
634                         }
635                         *val.data = data_blob_talloc(enum_values, data, data_size);
636                 }
637
638                 enum_values[i] = val;
639         }
640
641         *pnum_values = num_values;
642         if (penum_values) {
643                 *penum_values = talloc_move(mem_ctx, &enum_values);
644         }
645
646         result = WERR_OK;
647
648  error:
649         TALLOC_FREE(tmp_ctx);
650         return result;
651 }
652
653 /**
654  * @internal
655  *
656  * @brief Enumerate subkeys of an opened key handle and get the names.
657  *
658  * @param[in]  mem_ctx  The memory context to use.
659  *
660  * @param[in]  pipe_handle The pipe handle for the rpc connection.
661  *
662  * @param[in]  key_hnd  The opened key handle.
663  *
664  * @param[in]  pnum_subkeys A pointer to store the number of found subkeys.
665  *
666  * @param[in]  psubkeys A pointer to an array to store the found names of
667  *                      subkeys.
668  *
669  * @return                   WERR_OK on success, the corresponding DOS error
670  *                           code if something gone wrong.
671  */
672 static WERROR winreg_printer_enumkeys(TALLOC_CTX *mem_ctx,
673                                       struct rpc_pipe_client *pipe_handle,
674                                       struct policy_handle *key_hnd,
675                                       uint32_t *pnum_subkeys,
676                                       const char ***psubkeys)
677 {
678         TALLOC_CTX *tmp_ctx;
679         const char **subkeys;
680         uint32_t num_subkeys, max_subkeylen, max_classlen;
681         uint32_t num_values, max_valnamelen, max_valbufsize;
682         uint32_t i;
683         NTTIME last_changed_time;
684         uint32_t secdescsize;
685         struct winreg_String classname;
686         WERROR result = WERR_OK;
687         NTSTATUS status;
688
689         tmp_ctx = talloc_new(mem_ctx);
690         if (tmp_ctx == NULL) {
691                 return WERR_NOMEM;
692         }
693
694         ZERO_STRUCT(classname);
695
696         status = rpccli_winreg_QueryInfoKey(pipe_handle,
697                                             tmp_ctx,
698                                             key_hnd,
699                                             &classname,
700                                             &num_subkeys,
701                                             &max_subkeylen,
702                                             &max_classlen,
703                                             &num_values,
704                                             &max_valnamelen,
705                                             &max_valbufsize,
706                                             &secdescsize,
707                                             &last_changed_time,
708                                             &result);
709         if (!NT_STATUS_IS_OK(status)) {
710                 DEBUG(0, ("winreg_printer_enumkeys: Could not query info: %s\n",
711                           nt_errstr(status)));
712                 if (!W_ERROR_IS_OK(result)) {
713                         goto error;
714                 }
715                 result = ntstatus_to_werror(status);
716                 goto error;
717         }
718
719         subkeys = talloc_zero_array(tmp_ctx, const char *, num_subkeys + 2);
720         if (subkeys == NULL) {
721                 result = WERR_NOMEM;
722                 goto error;
723         }
724
725         if (num_subkeys == 0) {
726                 subkeys[0] = talloc_strdup(subkeys, "");
727                 if (subkeys[0] == NULL) {
728                         result = WERR_NOMEM;
729                         goto error;
730                 }
731                 *pnum_subkeys = 0;
732                 if (psubkeys) {
733                         *psubkeys = talloc_move(mem_ctx, &subkeys);
734                 }
735
736                 TALLOC_FREE(tmp_ctx);
737                 return WERR_OK;
738         }
739
740         for (i = 0; i < num_subkeys; i++) {
741                 char c = '\0';
742                 char n = '\0';
743                 char *name = NULL;
744                 struct winreg_StringBuf class_buf;
745                 struct winreg_StringBuf name_buf;
746                 NTTIME modtime;
747
748                 class_buf.name = &c;
749                 class_buf.size = max_classlen + 2;
750                 class_buf.length = 0;
751
752                 name_buf.name = &n;
753                 name_buf.size = max_subkeylen + 2;
754                 name_buf.length = 0;
755
756                 ZERO_STRUCT(modtime);
757
758                 status = rpccli_winreg_EnumKey(pipe_handle,
759                                                tmp_ctx,
760                                                key_hnd,
761                                                i,
762                                                &name_buf,
763                                                &class_buf,
764                                                &modtime,
765                                                &result);
766                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
767                         result = WERR_OK;
768                         status = NT_STATUS_OK;
769                         break;
770                 }
771
772                 if (!NT_STATUS_IS_OK(status)) {
773                         DEBUG(0, ("winreg_printer_enumkeys: Could not enumerate keys: %s\n",
774                                   nt_errstr(status)));
775                         if (!W_ERROR_IS_OK(result)) {
776                                 goto error;
777                         }
778                         result = ntstatus_to_werror(status);
779                         goto error;
780                 }
781
782                 if (name_buf.name == NULL) {
783                         result = WERR_INVALID_PARAMETER;
784                         goto error;
785                 }
786
787                 name = talloc_strdup(subkeys, name_buf.name);
788                 if (name == NULL) {
789                         result = WERR_NOMEM;
790                         goto error;
791                 }
792
793                 subkeys[i] = name;
794         }
795
796         *pnum_subkeys = num_subkeys;
797         if (psubkeys) {
798                 *psubkeys = talloc_move(mem_ctx, &subkeys);
799         }
800
801  error:
802         TALLOC_FREE(tmp_ctx);
803         return result;
804 }
805
806 /**
807  * @internal
808  *
809  * @brief A function to delete a key and its subkeys recurively.
810  *
811  * @param[in]  mem_ctx  The memory context to use.
812  *
813  * @param[in]  pipe_handle The pipe handle for the rpc connection.
814  *
815  * @param[in]  hive_handle A opened hive handle to the key.
816  *
817  * @param[in]  access_mask The access mask to access the key.
818  *
819  * @param[in]  key      The key to delete
820  *
821  * @return              WERR_OK on success, the corresponding DOS error
822  *                      code if something gone wrong.
823  */
824 static WERROR winreg_printer_delete_subkeys(TALLOC_CTX *mem_ctx,
825                                             struct rpc_pipe_client *pipe_handle,
826                                             struct policy_handle *hive_handle,
827                                             uint32_t access_mask,
828                                             const char *key)
829 {
830         const char **subkeys = NULL;
831         uint32_t num_subkeys = 0;
832         struct policy_handle key_hnd;
833         struct winreg_String wkey;
834         WERROR result = WERR_OK;
835         NTSTATUS status;
836         uint32_t i;
837
838         ZERO_STRUCT(key_hnd);
839         wkey.name = key;
840
841         DEBUG(2, ("winreg_printer_delete_subkeys: delete key %s\n", key));
842         /* open the key */
843         status = rpccli_winreg_OpenKey(pipe_handle,
844                                        mem_ctx,
845                                        hive_handle,
846                                        wkey,
847                                        0,
848                                        access_mask,
849                                        &key_hnd,
850                                        &result);
851         if (!NT_STATUS_IS_OK(status)) {
852                 DEBUG(0, ("winreg_printer_delete_subkeys: Could not open key %s: %s\n",
853                           wkey.name, nt_errstr(status)));
854                 if (!W_ERROR_IS_OK(result)) {
855                         return result;
856                 }
857                 return ntstatus_to_werror(status);
858         }
859
860         result = winreg_printer_enumkeys(mem_ctx,
861                                          pipe_handle,
862                                          &key_hnd,
863                                          &num_subkeys,
864                                          &subkeys);
865         if (!W_ERROR_IS_OK(result)) {
866                 goto done;
867         }
868
869         for (i = 0; i < num_subkeys; i++) {
870                 /* create key + subkey */
871                 char *subkey = talloc_asprintf(mem_ctx, "%s\\%s", key, subkeys[i]);
872                 if (subkey == NULL) {
873                         goto done;
874                 }
875
876                 DEBUG(2, ("winreg_printer_delete_subkeys: delete subkey %s\n", subkey));
877                 result = winreg_printer_delete_subkeys(mem_ctx,
878                                                        pipe_handle,
879                                                        hive_handle,
880                                                        access_mask,
881                                                        subkey);
882                 if (!W_ERROR_IS_OK(result)) {
883                         goto done;
884                 }
885         }
886
887         if (is_valid_policy_hnd(&key_hnd)) {
888                 rpccli_winreg_CloseKey(pipe_handle, mem_ctx, &key_hnd, NULL);
889         }
890
891         wkey.name = key;
892
893         status = rpccli_winreg_DeleteKey(pipe_handle,
894                                          mem_ctx,
895                                          hive_handle,
896                                          wkey,
897                                          &result);
898
899 done:
900         if (is_valid_policy_hnd(&key_hnd)) {
901                 rpccli_winreg_CloseKey(pipe_handle, mem_ctx, &key_hnd, NULL);
902         }
903
904         return result;
905 }
906
907 static WERROR winreg_printer_write_sz(TALLOC_CTX *mem_ctx,
908                                       struct rpc_pipe_client *pipe_handle,
909                                       struct policy_handle *key_handle,
910                                       const char *value,
911                                       const char *data)
912 {
913         struct winreg_String wvalue;
914         DATA_BLOB blob;
915         WERROR result = WERR_OK;
916         NTSTATUS status;
917
918         wvalue.name = value;
919         if (data == NULL) {
920                 blob = data_blob_string_const("");
921         } else {
922                 if (!push_reg_sz(mem_ctx, NULL, &blob, data)) {
923                         DEBUG(0, ("winreg_printer_write_sz: Could not marshall string %s for %s\n",
924                                 data, wvalue.name));
925                         return WERR_NOMEM;
926                 }
927         }
928         status = rpccli_winreg_SetValue(pipe_handle,
929                                         mem_ctx,
930                                         key_handle,
931                                         wvalue,
932                                         REG_SZ,
933                                         blob.data,
934                                         blob.length,
935                                         &result);
936         if (!NT_STATUS_IS_OK(status)) {
937                 DEBUG(0, ("winreg_printer_write_sz: Could not set value %s: %s\n",
938                         wvalue.name, win_errstr(result)));
939                 if (!W_ERROR_IS_OK(result)) {
940                         result = ntstatus_to_werror(status);
941                 }
942         }
943
944         return result;
945 }
946
947 static WERROR winreg_printer_write_dword(TALLOC_CTX *mem_ctx,
948                                          struct rpc_pipe_client *pipe_handle,
949                                          struct policy_handle *key_handle,
950                                          const char *value,
951                                          uint32_t data)
952 {
953         struct winreg_String wvalue;
954         DATA_BLOB blob;
955         WERROR result = WERR_OK;
956         NTSTATUS status;
957
958         wvalue.name = value;
959         blob = data_blob_talloc(mem_ctx, NULL, 4);
960         SIVAL(blob.data, 0, data);
961
962         status = rpccli_winreg_SetValue(pipe_handle,
963                                         mem_ctx,
964                                         key_handle,
965                                         wvalue,
966                                         REG_DWORD,
967                                         blob.data,
968                                         blob.length,
969                                         &result);
970         if (!NT_STATUS_IS_OK(status)) {
971                 DEBUG(0, ("winreg_printer_write_dword: Could not set value %s: %s\n",
972                         wvalue.name, win_errstr(result)));
973                 if (!W_ERROR_IS_OK(result)) {
974                         result = ntstatus_to_werror(status);
975                 }
976         }
977
978         return result;
979 }
980
981 static WERROR winreg_printer_write_binary(TALLOC_CTX *mem_ctx,
982                                           struct rpc_pipe_client *pipe_handle,
983                                           struct policy_handle *key_handle,
984                                           const char *value,
985                                           DATA_BLOB blob)
986 {
987         struct winreg_String wvalue;
988         WERROR result = WERR_OK;
989         NTSTATUS status;
990
991         wvalue.name = value;
992         status = rpccli_winreg_SetValue(pipe_handle,
993                                         mem_ctx,
994                                         key_handle,
995                                         wvalue,
996                                         REG_BINARY,
997                                         blob.data,
998                                         blob.length,
999                                         &result);
1000         if (!NT_STATUS_IS_OK(status)) {
1001                 DEBUG(0, ("winreg_printer_write_binary: Could not set value %s: %s\n",
1002                         wvalue.name, win_errstr(result)));
1003                 if (!W_ERROR_IS_OK(result)) {
1004                         result = ntstatus_to_werror(status);
1005                 }
1006         }
1007
1008         return result;
1009 }
1010
1011 static WERROR winreg_printer_query_dword(TALLOC_CTX *mem_ctx,
1012                                          struct rpc_pipe_client *pipe_handle,
1013                                          struct policy_handle *key_handle,
1014                                          const char *value,
1015                                          uint32_t *data)
1016 {
1017         struct winreg_String wvalue;
1018         enum winreg_Type type;
1019         WERROR result = WERR_OK;
1020         uint32_t value_len = 0;
1021         NTSTATUS status;
1022         DATA_BLOB blob;
1023
1024         wvalue.name = value;
1025         status = rpccli_winreg_QueryValue(pipe_handle,
1026                                           mem_ctx,
1027                                           key_handle,
1028                                           &wvalue,
1029                                           &type,
1030                                           NULL,
1031                                           (uint32_t *) &blob.length,
1032                                           &value_len,
1033                                           &result);
1034         if (!NT_STATUS_IS_OK(status)) {
1035                 DEBUG(0, ("winreg_printer_query_dword: Could not query value %s: %s\n",
1036                           wvalue.name, nt_errstr(status)));
1037                 if (!W_ERROR_IS_OK(result)) {
1038                         goto done;
1039                 }
1040                 result = ntstatus_to_werror(status);
1041                 goto done;
1042         }
1043
1044         if (type != REG_DWORD) {
1045                 result = WERR_INVALID_DATATYPE;
1046                 goto done;
1047         }
1048
1049         if (blob.length != 4) {
1050                 result = WERR_INVALID_DATA;
1051                 goto done;
1052         }
1053
1054         blob.data = (uint8_t *) TALLOC(mem_ctx, blob.length);
1055         if (blob.data == NULL) {
1056                 result = WERR_NOMEM;
1057                 goto done;
1058         }
1059         value_len = 0;
1060
1061         status = rpccli_winreg_QueryValue(pipe_handle,
1062                                           mem_ctx,
1063                                           key_handle,
1064                                           &wvalue,
1065                                           &type,
1066                                           blob.data,
1067                                           (uint32_t *) &blob.length,
1068                                           &value_len,
1069                                           &result);
1070         if (!NT_STATUS_IS_OK(status)) {
1071                 DEBUG(0, ("winreg_printer_query_dword: Could not query value %s: %s\n",
1072                           wvalue.name, nt_errstr(status)));
1073                 if (!W_ERROR_IS_OK(result)) {
1074                         result = ntstatus_to_werror(status);
1075                 }
1076                 goto done;
1077         }
1078
1079         if (data) {
1080                 *data = IVAL(blob.data, 0);
1081         }
1082 done:
1083         return result;
1084 }
1085
1086 static WERROR winreg_printer_write_multi_sz(TALLOC_CTX *mem_ctx,
1087                                             struct rpc_pipe_client *pipe_handle,
1088                                             struct policy_handle *key_handle,
1089                                             const char *value,
1090                                             const char **data)
1091 {
1092         struct winreg_String wvalue;
1093         DATA_BLOB blob;
1094         WERROR result = WERR_OK;
1095         NTSTATUS status;
1096
1097         wvalue.name = value;
1098         if (!push_reg_multi_sz(mem_ctx, NULL, &blob, data)) {
1099                 return WERR_NOMEM;
1100         }
1101         status = rpccli_winreg_SetValue(pipe_handle,
1102                                         mem_ctx,
1103                                         key_handle,
1104                                         wvalue,
1105                                         REG_MULTI_SZ,
1106                                         blob.data,
1107                                         blob.length,
1108                                         &result);
1109         if (!NT_STATUS_IS_OK(status)) {
1110                 DEBUG(0, ("winreg_printer_write_multi_sz: Could not set value %s: %s\n",
1111                         wvalue.name, win_errstr(result)));
1112                 if (!W_ERROR_IS_OK(result)) {
1113                         result = ntstatus_to_werror(status);
1114                 }
1115         }
1116
1117         return result;
1118 }
1119
1120 static WERROR winreg_printer_opendriver(TALLOC_CTX *mem_ctx,
1121                                         struct auth_serversupplied_info *server_info,
1122                                         const char *drivername,
1123                                         const char *architecture,
1124                                         uint32_t version,
1125                                         uint32_t access_mask,
1126                                         bool create,
1127                                         struct rpc_pipe_client **winreg_pipe,
1128                                         struct policy_handle *hive_hnd,
1129                                         struct policy_handle *key_hnd)
1130 {
1131         WERROR result;
1132         char *key_name;
1133
1134         key_name = talloc_asprintf(mem_ctx, "%s\\Environments\\%s\\Drivers\\Version-%u",
1135                                    TOP_LEVEL_CONTROL_KEY,
1136                                    architecture, version);
1137         if (!key_name) {
1138                 return WERR_NOMEM;
1139         }
1140
1141         result = winreg_printer_openkey(mem_ctx,
1142                                         server_info,
1143                                         winreg_pipe,
1144                                         key_name,
1145                                         drivername,
1146                                         create,
1147                                         access_mask,
1148                                         hive_hnd,
1149                                         key_hnd);
1150         return result;
1151 }
1152
1153 static WERROR winreg_enumval_to_dword(TALLOC_CTX *mem_ctx,
1154                                       struct spoolss_PrinterEnumValues *v,
1155                                       const char *valuename, uint32_t *dw)
1156 {
1157         /* just return if it is not the one we are looking for */
1158         if (strcmp(valuename, v->value_name) != 0) {
1159                 return WERR_NOT_FOUND;
1160         }
1161
1162         if (v->type != REG_DWORD) {
1163                 return WERR_INVALID_DATATYPE;
1164         }
1165
1166         *dw = IVAL(v->data->data, 0);
1167         return WERR_OK;
1168 }
1169
1170 static WERROR winreg_enumval_to_sz(TALLOC_CTX *mem_ctx,
1171                                    struct spoolss_PrinterEnumValues *v,
1172                                    const char *valuename, const char **_str)
1173 {
1174         /* just return if it is not the one we are looking for */
1175         if (strcmp(valuename, v->value_name) != 0) {
1176                 return WERR_NOT_FOUND;
1177         }
1178
1179         if (v->type != REG_SZ) {
1180                 return WERR_INVALID_DATATYPE;
1181         }
1182
1183         if (!pull_reg_sz(mem_ctx, NULL, v->data, _str)) {
1184                 return WERR_NOMEM;
1185         }
1186
1187         return WERR_OK;
1188 }
1189
1190 static WERROR winreg_enumval_to_multi_sz(TALLOC_CTX *mem_ctx,
1191                                          struct spoolss_PrinterEnumValues *v,
1192                                          const char *valuename,
1193                                          const char ***array)
1194 {
1195         /* just return if it is not the one we are looking for */
1196         if (strcmp(valuename, v->value_name) != 0) {
1197                 return WERR_NOT_FOUND;
1198         }
1199
1200         if (v->type != REG_MULTI_SZ) {
1201                 return WERR_INVALID_DATATYPE;
1202         }
1203
1204         if (!pull_reg_multi_sz(mem_ctx, NULL, v->data, array)) {
1205                 return WERR_NOMEM;
1206         }
1207
1208         return WERR_OK;
1209 }
1210
1211 static WERROR winreg_enumval_to_blob(TALLOC_CTX *mem_ctx,
1212                                      struct spoolss_PrinterEnumValues *v,
1213                                      const char *valuename,
1214                                      DATA_BLOB *blob)
1215 {
1216         /* just return if it is not the one we are looking for */
1217         if (strcmp(valuename, v->value_name) != 0) {
1218                 return WERR_NOT_FOUND;
1219         }
1220
1221         if (v->type != REG_BINARY) {
1222                 return WERR_INVALID_DATATYPE;
1223         }
1224
1225         blob->data = v->data->data;
1226         blob->length = v->data_length;
1227
1228         return WERR_OK;
1229 }
1230
1231 static WERROR winreg_printer_write_date(TALLOC_CTX *mem_ctx,
1232                                         struct rpc_pipe_client *pipe_handle,
1233                                         struct policy_handle *key_handle,
1234                                         const char *value,
1235                                         NTTIME data)
1236 {
1237         struct winreg_String wvalue;
1238         DATA_BLOB blob;
1239         WERROR result = WERR_OK;
1240         NTSTATUS status;
1241         const char *str;
1242         struct tm *tm;
1243         time_t t;
1244
1245         t = nt_time_to_unix(data);
1246         tm = localtime(&t);
1247         str = talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
1248                               tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
1249         if (!str) {
1250                 return WERR_NOMEM;
1251         }
1252
1253         wvalue.name = value;
1254         if (!push_reg_sz(mem_ctx, NULL, &blob, str)) {
1255                 return WERR_NOMEM;
1256         }
1257         status = rpccli_winreg_SetValue(pipe_handle,
1258                                         mem_ctx,
1259                                         key_handle,
1260                                         wvalue,
1261                                         REG_SZ,
1262                                         blob.data,
1263                                         blob.length,
1264                                         &result);
1265         if (!NT_STATUS_IS_OK(status)) {
1266                 DEBUG(0, ("winreg_printer_write_date: Could not set value %s: %s\n",
1267                         wvalue.name, win_errstr(result)));
1268                 if (!W_ERROR_IS_OK(result)) {
1269                         result = ntstatus_to_werror(status);
1270                 }
1271         }
1272
1273         return result;
1274 }
1275
1276 static WERROR winreg_printer_date_to_NTTIME(const char *str, NTTIME *data)
1277 {
1278         struct tm tm;
1279         time_t t;
1280
1281         ZERO_STRUCT(tm);
1282
1283         if (sscanf(str, "%d/%d/%d",
1284                    &tm.tm_mon, &tm.tm_mday, &tm.tm_year) != 3) {
1285                 return WERR_INVALID_PARAMETER;
1286         }
1287         tm.tm_mon -= 1;
1288         tm.tm_year -= 1900;
1289         tm.tm_isdst = -1;
1290
1291         t = mktime(&tm);
1292         unix_to_nt_time(data, t);
1293
1294         return WERR_OK;
1295 }
1296
1297 static WERROR winreg_printer_write_ver(TALLOC_CTX *mem_ctx,
1298                                        struct rpc_pipe_client *pipe_handle,
1299                                        struct policy_handle *key_handle,
1300                                        const char *value,
1301                                        uint64_t data)
1302 {
1303         struct winreg_String wvalue;
1304         DATA_BLOB blob;
1305         WERROR result = WERR_OK;
1306         NTSTATUS status;
1307         char *str;
1308
1309         /* FIXME: check format is right,
1310          *      this needs to be something like: 6.1.7600.16385 */
1311         str = talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
1312                               (unsigned)((data >> 48) & 0xFFFF),
1313                               (unsigned)((data >> 32) & 0xFFFF),
1314                               (unsigned)((data >> 16) & 0xFFFF),
1315                               (unsigned)(data & 0xFFFF));
1316         if (!str) {
1317                 return WERR_NOMEM;
1318         }
1319
1320         wvalue.name = value;
1321         if (!push_reg_sz(mem_ctx, NULL, &blob, str)) {
1322                 return WERR_NOMEM;
1323         }
1324         status = rpccli_winreg_SetValue(pipe_handle,
1325                                         mem_ctx,
1326                                         key_handle,
1327                                         wvalue,
1328                                         REG_SZ,
1329                                         blob.data,
1330                                         blob.length,
1331                                         &result);
1332         if (!NT_STATUS_IS_OK(status)) {
1333                 DEBUG(0, ("winreg_printer_write_date: Could not set value %s: %s\n",
1334                         wvalue.name, win_errstr(result)));
1335                 if (!W_ERROR_IS_OK(result)) {
1336                         result = ntstatus_to_werror(status);
1337                 }
1338         }
1339
1340         return result;
1341 }
1342
1343 static WERROR winreg_printer_ver_to_dword(const char *str, uint64_t *data)
1344 {
1345         unsigned int v1, v2, v3, v4;
1346
1347         if (sscanf(str, "%u.%u.%u.%u", &v1, &v2, &v3, &v4) != 4) {
1348                 return WERR_INVALID_PARAMETER;
1349         }
1350
1351         *data = ((uint64_t)(v1 & 0xFFFF) << 48) +
1352                 ((uint64_t)(v2 & 0xFFFF) << 32) +
1353                 ((uint64_t)(v3 & 0xFFFF) << 16) +
1354                 (uint64_t)(v2 & 0xFFFF);
1355
1356         return WERR_OK;
1357 }
1358
1359 /********************************************************************
1360  Public winreg function for spoolss
1361 ********************************************************************/
1362
1363 WERROR winreg_create_printer(TALLOC_CTX *mem_ctx,
1364                              struct auth_serversupplied_info *server_info,
1365                              const char *servername,
1366                              const char *sharename)
1367 {
1368         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1369         struct rpc_pipe_client *winreg_pipe = NULL;
1370         struct policy_handle hive_hnd, key_hnd;
1371         struct spoolss_SetPrinterInfo2 *info2;
1372         struct spoolss_DeviceMode *devmode = NULL;
1373         struct security_descriptor *secdesc;
1374         struct winreg_String wkey, wkeyclass;
1375         const char *path;
1376         const char *subkeys[] = { "DsDriver", "DsSpooler", "PrinterDriverData" };
1377         uint32_t i, count = ARRAY_SIZE(subkeys);
1378         int snum = lp_servicenumber(sharename);
1379         uint32_t info2_mask = 0;
1380         WERROR result = WERR_OK;
1381         TALLOC_CTX *tmp_ctx;
1382
1383         tmp_ctx = talloc_new(mem_ctx);
1384         if (tmp_ctx == NULL) {
1385                 return WERR_NOMEM;
1386         }
1387
1388         path = winreg_printer_data_keyname(tmp_ctx, sharename);
1389         if (path == NULL) {
1390                 TALLOC_FREE(tmp_ctx);
1391                 return WERR_NOMEM;
1392         }
1393
1394         ZERO_STRUCT(hive_hnd);
1395         ZERO_STRUCT(key_hnd);
1396
1397         result = winreg_printer_openkey(tmp_ctx,
1398                                         server_info,
1399                                         &winreg_pipe,
1400                                         path,
1401                                         "",
1402                                         false,
1403                                         access_mask,
1404                                         &hive_hnd,
1405                                         &key_hnd);
1406         if (W_ERROR_IS_OK(result)) {
1407                 DEBUG(2, ("winreg_create_printer: Skipping, %s already exists\n", path));
1408                 goto done;
1409         } else if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1410                 DEBUG(2, ("winreg_create_printer: Creating default values in %s\n", path));
1411         } else if (!W_ERROR_IS_OK(result)) {
1412                 DEBUG(0, ("winreg_create_printer: Could not open key %s: %s\n",
1413                         path, win_errstr(result)));
1414                 goto done;
1415         }
1416
1417         /* Create the main key */
1418         result = winreg_printer_openkey(tmp_ctx,
1419                                         server_info,
1420                                         &winreg_pipe,
1421                                         path,
1422                                         "",
1423                                         true,
1424                                         access_mask,
1425                                         &hive_hnd,
1426                                         &key_hnd);
1427         if (!W_ERROR_IS_OK(result)) {
1428                 DEBUG(0, ("winreg_create_printer_keys: Could not create key %s: %s\n",
1429                         path, win_errstr(result)));
1430                 goto done;
1431         }
1432
1433         if (is_valid_policy_hnd(&key_hnd)) {
1434                 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1435         }
1436
1437         /* Create subkeys */
1438         for (i = 0; i < count; i++) {
1439                 NTSTATUS status;
1440                 enum winreg_CreateAction action = REG_ACTION_NONE;
1441
1442                 ZERO_STRUCT(key_hnd);
1443                 ZERO_STRUCT(wkey);
1444
1445                 wkey.name = talloc_asprintf(tmp_ctx, "%s\\%s", path, subkeys[i]);
1446                 if (wkey.name == NULL) {
1447                         result = WERR_NOMEM;
1448                         goto done;
1449                 }
1450
1451                 ZERO_STRUCT(wkeyclass);
1452                 wkeyclass.name = "";
1453
1454                 status = rpccli_winreg_CreateKey(winreg_pipe,
1455                                                  tmp_ctx,
1456                                                  &hive_hnd,
1457                                                  wkey,
1458                                                  wkeyclass,
1459                                                  0,
1460                                                  access_mask,
1461                                                  NULL,
1462                                                  &key_hnd,
1463                                                  &action,
1464                                                  &result);
1465                 if (!NT_STATUS_IS_OK(status)) {
1466                         DEBUG(0, ("winreg_create_printer_keys: Could not create key %s: %s\n",
1467                                 wkey.name, win_errstr(result)));
1468                         if (!W_ERROR_IS_OK(result)) {
1469                                 result = ntstatus_to_werror(status);
1470                         }
1471                         goto done;
1472                 }
1473
1474                 if (is_valid_policy_hnd(&key_hnd)) {
1475                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1476                 }
1477         }
1478         info2 = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
1479         if (info2 == NULL) {
1480                 result = WERR_NOMEM;
1481                 goto done;
1482         }
1483
1484         info2->printername = sharename;
1485         info2_mask |= SPOOLSS_PRINTER_INFO_PRINTERNAME;
1486
1487         info2->sharename = sharename;
1488         info2_mask |= SPOOLSS_PRINTER_INFO_SHARENAME;
1489
1490         info2->portname = SAMBA_PRINTER_PORT_NAME;
1491         info2_mask |= SPOOLSS_PRINTER_INFO_PORTNAME;
1492
1493         info2->printprocessor = "winprint";
1494         info2_mask |= SPOOLSS_PRINTER_INFO_PRINTPROCESSOR;
1495
1496         info2->datatype = "RAW";
1497         info2_mask |= SPOOLSS_PRINTER_INFO_DATATYPE;
1498
1499         info2->comment = "";
1500         info2_mask |= SPOOLSS_PRINTER_INFO_COMMENT;
1501
1502         info2->attributes = PRINTER_ATTRIBUTE_SAMBA;
1503         info2_mask |= SPOOLSS_PRINTER_INFO_ATTRIBUTES;
1504
1505         info2->starttime = 0; /* Minutes since 12:00am GMT */
1506         info2_mask |= SPOOLSS_PRINTER_INFO_STARTTIME;
1507
1508         info2->untiltime = 0; /* Minutes since 12:00am GMT */
1509         info2_mask |= SPOOLSS_PRINTER_INFO_UNTILTIME;
1510
1511         info2->priority = 1;
1512         info2_mask |= SPOOLSS_PRINTER_INFO_PRIORITY;
1513
1514         info2->defaultpriority = 1;
1515         info2_mask |= SPOOLSS_PRINTER_INFO_DEFAULTPRIORITY;
1516
1517         /* info2->setuptime = (uint32_t) time(NULL); */
1518
1519         if (lp_default_devmode(snum)) {
1520                 devmode = winreg_printer_create_default_devmode(tmp_ctx,
1521                                                                 info2->printername);
1522                 if (devmode == NULL) {
1523                         result = WERR_NOMEM;
1524                         goto done;
1525                 }
1526
1527                 info2_mask |= SPOOLSS_PRINTER_INFO_DEVMODE;
1528         }
1529
1530         secdesc = winreg_printer_create_default_secdesc(tmp_ctx);
1531         if (secdesc == NULL) {
1532                 result = WERR_NOMEM;
1533                 goto done;
1534         }
1535         info2_mask |= SPOOLSS_PRINTER_INFO_SECDESC;
1536
1537         result = winreg_update_printer(tmp_ctx,
1538                                        server_info,
1539                                        sharename,
1540                                        info2_mask,
1541                                        info2,
1542                                        devmode,
1543                                        secdesc);
1544
1545 done:
1546         if (winreg_pipe != NULL) {
1547                 if (is_valid_policy_hnd(&key_hnd)) {
1548                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1549                 }
1550                 if (is_valid_policy_hnd(&hive_hnd)) {
1551                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1552                 }
1553         }
1554
1555         talloc_free(tmp_ctx);
1556         return result;
1557 }
1558
1559 WERROR winreg_update_printer(TALLOC_CTX *mem_ctx,
1560                              struct auth_serversupplied_info *server_info,
1561                              const char *sharename,
1562                              uint32_t info2_mask,
1563                              struct spoolss_SetPrinterInfo2 *info2,
1564                              struct spoolss_DeviceMode *devmode,
1565                              struct security_descriptor *secdesc)
1566 {
1567         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1568         struct rpc_pipe_client *winreg_pipe = NULL;
1569         struct policy_handle hive_hnd, key_hnd;
1570         enum ndr_err_code ndr_err;
1571         DATA_BLOB blob;
1572         char *path;
1573         WERROR result = WERR_OK;
1574         TALLOC_CTX *tmp_ctx;
1575
1576         tmp_ctx = talloc_new(mem_ctx);
1577         if (tmp_ctx == NULL) {
1578                 return WERR_NOMEM;
1579         }
1580
1581         path = winreg_printer_data_keyname(tmp_ctx, sharename);
1582         if (path == NULL) {
1583                 TALLOC_FREE(tmp_ctx);
1584                 return WERR_NOMEM;
1585         }
1586
1587         ZERO_STRUCT(hive_hnd);
1588         ZERO_STRUCT(key_hnd);
1589
1590         result = winreg_printer_openkey(tmp_ctx,
1591                                         server_info,
1592                                         &winreg_pipe,
1593                                         path,
1594                                         "",
1595                                         true,
1596                                         access_mask,
1597                                         &hive_hnd,
1598                                         &key_hnd);
1599         if (!W_ERROR_IS_OK(result)) {
1600                 DEBUG(0, ("winreg_update_printer: Could not open key %s: %s\n",
1601                         path, win_errstr(result)));
1602                 goto done;
1603         }
1604
1605         if (info2_mask & SPOOLSS_PRINTER_INFO_ATTRIBUTES) {
1606                 result = winreg_printer_write_dword(tmp_ctx,
1607                                                     winreg_pipe,
1608                                                     &key_hnd,
1609                                                     "Attributes",
1610                                                     info2->attributes);
1611                 if (!W_ERROR_IS_OK(result)) {
1612                         goto done;
1613                 }
1614         }
1615
1616 #if 0
1617         if (info2_mask & SPOOLSS_PRINTER_INFO_AVERAGEPPM) {
1618                 result = winreg_printer_write_dword(tmp_ctx,
1619                                                     winreg_pipe,
1620                                                     &key_hnd,
1621                                                     "AveragePpm",
1622                                                     info2->attributes);
1623                 if (!W_ERROR_IS_OK(result)) {
1624                         goto done;
1625                 }
1626         }
1627 #endif
1628
1629         if (info2_mask & SPOOLSS_PRINTER_INFO_COMMENT) {
1630                 result = winreg_printer_write_sz(tmp_ctx,
1631                                                  winreg_pipe,
1632                                                  &key_hnd,
1633                                                  "Description",
1634                                                  info2->comment);
1635                 if (!W_ERROR_IS_OK(result)) {
1636                         goto done;
1637                 }
1638         }
1639
1640         if (info2_mask & SPOOLSS_PRINTER_INFO_DATATYPE) {
1641                 result = winreg_printer_write_sz(tmp_ctx,
1642                                                  winreg_pipe,
1643                                                  &key_hnd,
1644                                                  "Datatype",
1645                                                  info2->datatype);
1646                 if (!W_ERROR_IS_OK(result)) {
1647                         goto done;
1648                 }
1649         }
1650
1651         if (info2_mask & SPOOLSS_PRINTER_INFO_DEFAULTPRIORITY) {
1652                 result = winreg_printer_write_dword(tmp_ctx,
1653                                                     winreg_pipe,
1654                                                     &key_hnd,
1655                                                     "Default Priority",
1656                                                     info2->defaultpriority);
1657                 if (!W_ERROR_IS_OK(result)) {
1658                         goto done;
1659                 }
1660         }
1661
1662         if (info2_mask & SPOOLSS_PRINTER_INFO_DEVMODE) {
1663                 ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL, devmode,
1664                                 (ndr_push_flags_fn_t) ndr_push_spoolss_DeviceMode);
1665                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1666                         DEBUG(0, ("winreg_update_printer: Failed to marshall device mode\n"));
1667                         result = WERR_NOMEM;
1668                         goto done;
1669                 }
1670
1671                 result = winreg_printer_write_binary(tmp_ctx,
1672                                                      winreg_pipe,
1673                                                      &key_hnd,
1674                                                      "Default DevMode",
1675                                                      blob);
1676                 if (!W_ERROR_IS_OK(result)) {
1677                         goto done;
1678                 }
1679         }
1680
1681         if (info2_mask & SPOOLSS_PRINTER_INFO_DRIVERNAME) {
1682                 result = winreg_printer_write_sz(tmp_ctx,
1683                                                  winreg_pipe,
1684                                                  &key_hnd,
1685                                                  "Printer Driver",
1686                                                  info2->drivername);
1687                 if (!W_ERROR_IS_OK(result)) {
1688                         goto done;
1689                 }
1690         }
1691
1692         if (info2_mask & SPOOLSS_PRINTER_INFO_LOCATION) {
1693                 result = winreg_printer_write_sz(tmp_ctx,
1694                                                  winreg_pipe,
1695                                                  &key_hnd,
1696                                                  "Location",
1697                                                  info2->location);
1698                 if (!W_ERROR_IS_OK(result)) {
1699                         goto done;
1700                 }
1701         }
1702
1703         if (info2_mask & SPOOLSS_PRINTER_INFO_PARAMETERS) {
1704                 result = winreg_printer_write_sz(tmp_ctx,
1705                                                  winreg_pipe,
1706                                                  &key_hnd,
1707                                                  "Parameters",
1708                                                  info2->parameters);
1709                 if (!W_ERROR_IS_OK(result)) {
1710                         goto done;
1711                 }
1712         }
1713
1714         if (info2_mask & SPOOLSS_PRINTER_INFO_PORTNAME) {
1715                 result = winreg_printer_write_sz(tmp_ctx,
1716                                                  winreg_pipe,
1717                                                  &key_hnd,
1718                                                  "Port",
1719                                                  info2->portname);
1720                 if (!W_ERROR_IS_OK(result)) {
1721                         goto done;
1722                 }
1723         }
1724
1725         if (info2_mask & SPOOLSS_PRINTER_INFO_PRINTERNAME) {
1726                 /*
1727                  * in addprinter: no servername and the printer is the name
1728                  * in setprinter: servername is \\server
1729                  *                and printer is \\server\\printer
1730                  *
1731                  * Samba manages only local printers.
1732                  * we currently don't support things like i
1733                  * path=\\other_server\printer
1734                  *
1735                  * We only store the printername, not \\server\printername
1736                  */
1737                 const char *p = strrchr(info2->printername, '\\');
1738                 if (p == NULL) {
1739                         p = info2->printername;
1740                 } else {
1741                         p++;
1742                 }
1743                 result = winreg_printer_write_sz(tmp_ctx,
1744                                                  winreg_pipe,
1745                                                  &key_hnd,
1746                                                  "Name",
1747                                                  p);
1748                 if (!W_ERROR_IS_OK(result)) {
1749                         goto done;
1750                 }
1751         }
1752
1753         if (info2_mask & SPOOLSS_PRINTER_INFO_PRINTPROCESSOR) {
1754                 result = winreg_printer_write_sz(tmp_ctx,
1755                                                  winreg_pipe,
1756                                                  &key_hnd,
1757                                                  "Print Processor",
1758                                                  info2->printprocessor);
1759                 if (!W_ERROR_IS_OK(result)) {
1760                         goto done;
1761                 }
1762         }
1763
1764         if (info2_mask & SPOOLSS_PRINTER_INFO_PRIORITY) {
1765                 result = winreg_printer_write_dword(tmp_ctx,
1766                                                     winreg_pipe,
1767                                                     &key_hnd,
1768                                                     "Priority",
1769                                                     info2->priority);
1770                 if (!W_ERROR_IS_OK(result)) {
1771                         goto done;
1772                 }
1773         }
1774
1775         if (info2_mask & SPOOLSS_PRINTER_INFO_SECDESC) {
1776                 /*
1777                  * We need a security descriptor, if it isn't specified by
1778                  * AddPrinter{Ex} then create a default descriptor.
1779                  */
1780                 if (secdesc == NULL) {
1781                         secdesc = winreg_printer_create_default_secdesc(tmp_ctx);
1782                 }
1783                 ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL, secdesc,
1784                                 (ndr_push_flags_fn_t) ndr_push_security_descriptor);
1785                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1786                         DEBUG(0, ("winreg_update_printer: Failed to marshall security descriptor\n"));
1787                         result = WERR_NOMEM;
1788                         goto done;
1789                 }
1790
1791                 result = winreg_printer_write_binary(tmp_ctx,
1792                                                      winreg_pipe,
1793                                                      &key_hnd,
1794                                                      "Security",
1795                                                      blob);
1796                 if (!W_ERROR_IS_OK(result)) {
1797                         goto done;
1798                 }
1799         }
1800
1801         if (info2_mask & SPOOLSS_PRINTER_INFO_SEPFILE) {
1802                 result = winreg_printer_write_sz(tmp_ctx,
1803                                                  winreg_pipe,
1804                                                  &key_hnd,
1805                                                  "Separator File",
1806                                                  info2->sepfile);
1807                 if (!W_ERROR_IS_OK(result)) {
1808                         goto done;
1809                 }
1810         }
1811
1812         if (info2_mask & SPOOLSS_PRINTER_INFO_SHARENAME) {
1813                 result = winreg_printer_write_sz(tmp_ctx,
1814                                                  winreg_pipe,
1815                                                  &key_hnd,
1816                                                  "Share Name",
1817                                                  info2->sharename);
1818                 if (!W_ERROR_IS_OK(result)) {
1819                         goto done;
1820                 }
1821         }
1822
1823         if (info2_mask & SPOOLSS_PRINTER_INFO_STARTTIME) {
1824                 result = winreg_printer_write_dword(tmp_ctx,
1825                                                     winreg_pipe,
1826                                                     &key_hnd,
1827                                                     "StartTime",
1828                                                     info2->starttime);
1829                 if (!W_ERROR_IS_OK(result)) {
1830                         goto done;
1831                 }
1832         }
1833
1834         if (info2_mask & SPOOLSS_PRINTER_INFO_STATUS) {
1835                 result = winreg_printer_write_dword(tmp_ctx,
1836                                                     winreg_pipe,
1837                                                     &key_hnd,
1838                                                     "Status",
1839                                                     info2->status);
1840                 if (!W_ERROR_IS_OK(result)) {
1841                         goto done;
1842                 }
1843         }
1844
1845         if (info2_mask & SPOOLSS_PRINTER_INFO_UNTILTIME) {
1846                 result = winreg_printer_write_dword(tmp_ctx,
1847                                                     winreg_pipe,
1848                                                     &key_hnd,
1849                                                     "UntilTime",
1850                                                     info2->untiltime);
1851                 if (!W_ERROR_IS_OK(result)) {
1852                         goto done;
1853                 }
1854         }
1855
1856         result = winreg_printer_write_dword(tmp_ctx,
1857                                             winreg_pipe,
1858                                             &key_hnd,
1859                                             "ChangeID",
1860                                             winreg_printer_rev_changeid());
1861         if (!W_ERROR_IS_OK(result)) {
1862                 goto done;
1863         }
1864
1865         result = WERR_OK;
1866 done:
1867         if (winreg_pipe != NULL) {
1868                 if (is_valid_policy_hnd(&key_hnd)) {
1869                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1870                 }
1871                 if (is_valid_policy_hnd(&hive_hnd)) {
1872                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1873                 }
1874         }
1875
1876         TALLOC_FREE(tmp_ctx);
1877         return result;
1878 }
1879
1880 WERROR winreg_get_printer(TALLOC_CTX *mem_ctx,
1881                           struct auth_serversupplied_info *server_info,
1882                           const char *servername,
1883                           const char *printer,
1884                           struct spoolss_PrinterInfo2 **pinfo2)
1885 {
1886         struct spoolss_PrinterInfo2 *info2;
1887         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1888         struct rpc_pipe_client *winreg_pipe = NULL;
1889         struct policy_handle hive_hnd, key_hnd;
1890         struct spoolss_PrinterEnumValues *enum_values = NULL;
1891         struct spoolss_PrinterEnumValues *v;
1892         enum ndr_err_code ndr_err;
1893         DATA_BLOB blob;
1894         uint32_t num_values = 0;
1895         uint32_t i;
1896         char *path;
1897         WERROR result = WERR_OK;
1898         TALLOC_CTX *tmp_ctx;
1899
1900         tmp_ctx = talloc_new(mem_ctx);
1901         if (tmp_ctx == NULL) {
1902                 return WERR_NOMEM;
1903         }
1904
1905         path = winreg_printer_data_keyname(tmp_ctx, printer);
1906         if (path == NULL) {
1907                 TALLOC_FREE(tmp_ctx);
1908                 return WERR_NOMEM;
1909         }
1910
1911         result = winreg_printer_openkey(tmp_ctx,
1912                                         server_info,
1913                                         &winreg_pipe,
1914                                         path,
1915                                         "",
1916                                         false,
1917                                         access_mask,
1918                                         &hive_hnd,
1919                                         &key_hnd);
1920         if (!W_ERROR_IS_OK(result)) {
1921                 DEBUG(0, ("winreg_get_printer: Could not open key %s: %s\n",
1922                           path, win_errstr(result)));
1923                 goto done;
1924         }
1925
1926         result = winreg_printer_enumvalues(tmp_ctx,
1927                                            winreg_pipe,
1928                                            &key_hnd,
1929                                            &num_values,
1930                                            &enum_values);
1931         if (!W_ERROR_IS_OK(result)) {
1932                 DEBUG(0, ("winreg_get_printer: Could not enumerate values in %s: %s\n",
1933                           path, win_errstr(result)));
1934                 goto done;
1935         }
1936
1937         info2 = talloc_zero(tmp_ctx, struct spoolss_PrinterInfo2);
1938         if (info2 == NULL) {
1939                 result = WERR_NOMEM;
1940                 goto done;
1941         }
1942
1943         info2->servername     = EMPTY_STRING;
1944         info2->printername    = EMPTY_STRING;
1945         info2->sharename      = EMPTY_STRING;
1946         info2->portname       = EMPTY_STRING;
1947         info2->drivername     = EMPTY_STRING;
1948         info2->comment        = EMPTY_STRING;
1949         info2->location       = EMPTY_STRING;
1950         info2->sepfile        = EMPTY_STRING;
1951         info2->printprocessor = EMPTY_STRING;
1952         info2->datatype       = EMPTY_STRING;
1953         info2->parameters     = EMPTY_STRING;
1954
1955         if (servername != NULL && servername[0] != '\0') {
1956                 info2->servername = talloc_asprintf(info2, "\\\\%s", servername);
1957                 if (info2->servername == NULL) {
1958                         result = WERR_NOMEM;
1959                         goto done;
1960                 }
1961         }
1962
1963         for (i = 0; i < num_values; i++) {
1964                 v = &enum_values[i];
1965
1966                 result = winreg_enumval_to_sz(info2,
1967                                               v,
1968                                               "Name",
1969                                               &info2->printername);
1970                 if (W_ERROR_IS_OK(result) && info2->servername[0] != '\0') {
1971                         char *p = talloc_asprintf(info2, "%s\\%s",
1972                                                   info2->servername,
1973                                                   info2->printername);
1974                         if (p == NULL) {
1975                                 result = WERR_NOMEM;
1976                         }
1977                         info2->printername = p;
1978                 }
1979                 CHECK_ERROR(result);
1980
1981                 result = winreg_enumval_to_sz(info2,
1982                                               v,
1983                                               "Share Name",
1984                                               &info2->sharename);
1985                 CHECK_ERROR(result);
1986
1987                 result = winreg_enumval_to_sz(info2,
1988                                               v,
1989                                               "Port",
1990                                               &info2->portname);
1991                 CHECK_ERROR(result);
1992
1993                 result = winreg_enumval_to_sz(info2,
1994                                               v,
1995                                               "Description",
1996                                               &info2->comment);
1997                 CHECK_ERROR(result);
1998
1999                 result = winreg_enumval_to_sz(info2,
2000                                               v,
2001                                               "Location",
2002                                               &info2->location);
2003                 CHECK_ERROR(result);
2004
2005                 result = winreg_enumval_to_sz(info2,
2006                                               v,
2007                                               "Separator File",
2008                                               &info2->sepfile);
2009                 CHECK_ERROR(result);
2010
2011                 result = winreg_enumval_to_sz(info2,
2012                                               v,
2013                                               "Print Processor",
2014                                               &info2->printprocessor);
2015                 CHECK_ERROR(result);
2016
2017                 result = winreg_enumval_to_sz(info2,
2018                                               v,
2019                                               "Datatype",
2020                                               &info2->datatype);
2021                 CHECK_ERROR(result);
2022
2023                 result = winreg_enumval_to_sz(info2,
2024                                               v,
2025                                               "Parameters",
2026                                               &info2->parameters);
2027                 CHECK_ERROR(result);
2028
2029                 result = winreg_enumval_to_sz(info2,
2030                                               v,
2031                                               "Printer Driver",
2032                                               &info2->drivername);
2033                 CHECK_ERROR(result);
2034
2035                 result = winreg_enumval_to_dword(info2,
2036                                                  v,
2037                                                  "Attributes",
2038                                                  &info2->attributes);
2039                 CHECK_ERROR(result);
2040
2041                 result = winreg_enumval_to_dword(info2,
2042                                                  v,
2043                                                  "Priority",
2044                                                  &info2->priority);
2045                 CHECK_ERROR(result);
2046
2047                 result = winreg_enumval_to_dword(info2,
2048                                                  v,
2049                                                  "Default Priority",
2050                                                  &info2->defaultpriority);
2051                 CHECK_ERROR(result);
2052
2053                 result = winreg_enumval_to_dword(info2,
2054                                                  v,
2055                                                  "StartTime",
2056                                                  &info2->starttime);
2057                 CHECK_ERROR(result);
2058
2059                 result = winreg_enumval_to_dword(info2,
2060                                                  v,
2061                                                  "UntilTime",
2062                                                  &info2->untiltime);
2063                 CHECK_ERROR(result);
2064
2065                 result = winreg_enumval_to_dword(info2,
2066                                                  v,
2067                                                  "Status",
2068                                                  &info2->status);
2069                 CHECK_ERROR(result);
2070
2071                 result = winreg_enumval_to_dword(info2,
2072                                                  v,
2073                                                  "StartTime",
2074                                                  &info2->starttime);
2075                 CHECK_ERROR(result);
2076
2077                 result = winreg_enumval_to_blob(info2,
2078                                                 v,
2079                                                 "Default DevMode",
2080                                                 &blob);
2081                 if (W_ERROR_IS_OK(result)) {
2082                         info2->devmode = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2083                         if (info2->devmode == NULL) {
2084                                 result = WERR_NOMEM;
2085                                 goto done;
2086                         }
2087                         ndr_err = ndr_pull_struct_blob(&blob,
2088                                                        info2,
2089                                                        NULL,
2090                                                        info2->devmode,
2091                                                        (ndr_pull_flags_fn_t) ndr_pull_spoolss_DeviceMode);
2092                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2093                                 DEBUG(0, ("winreg_get_printer: Failed to unmarshall device mode\n"));
2094                                 result = WERR_NOMEM;
2095                                 goto done;
2096                         }
2097                 }
2098                 CHECK_ERROR(result);
2099
2100                 result = winreg_enumval_to_blob(info2,
2101                                                 v,
2102                                                 "Security",
2103                                                 &blob);
2104                 if (W_ERROR_IS_OK(result)) {
2105                         info2->secdesc = talloc_zero(mem_ctx, struct spoolss_security_descriptor);
2106                         if (info2->secdesc == NULL) {
2107                                 result = WERR_NOMEM;
2108                                 goto done;
2109                         }
2110                         ndr_err = ndr_pull_struct_blob(&blob,
2111                                                        mem_ctx,
2112                                                        NULL,
2113                                                        info2->secdesc,
2114                                                        (ndr_pull_flags_fn_t) ndr_pull_security_descriptor);
2115                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2116                                 DEBUG(0, ("winreg_get_printer: Failed to unmarshall security descriptor\n"));
2117                                 result = WERR_NOMEM;
2118                                 goto done;
2119                         }
2120                 }
2121                 CHECK_ERROR(result);
2122         }
2123
2124         if (!W_ERROR_IS_OK(result)) {
2125                 DEBUG(0, ("winreg_get_printer: winreg_enumval_to_TYPE() failed "
2126                                         "for %s: %s\n",
2127                                         v->value_name,
2128                                         win_errstr(result)));
2129                 goto done;
2130         }
2131
2132         if (pinfo2) {
2133                 *pinfo2 = talloc_move(mem_ctx, &info2);
2134         }
2135
2136         result = WERR_OK;
2137 done:
2138         if (winreg_pipe != NULL) {
2139                 if (is_valid_policy_hnd(&key_hnd)) {
2140                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2141                 }
2142                 if (is_valid_policy_hnd(&hive_hnd)) {
2143                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2144                 }
2145         }
2146
2147         TALLOC_FREE(tmp_ctx);
2148         return result;
2149 }
2150
2151 /* Set printer data over the winreg pipe. */
2152 WERROR winreg_set_printer_dataex(TALLOC_CTX *mem_ctx,
2153                                  struct auth_serversupplied_info *server_info,
2154                                  const char *printer,
2155                                  const char *key,
2156                                  const char *value,
2157                                  enum winreg_Type type,
2158                                  uint8_t *data,
2159                                  uint32_t data_size)
2160 {
2161         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2162         struct rpc_pipe_client *winreg_pipe = NULL;
2163         struct policy_handle hive_hnd, key_hnd;
2164         struct winreg_String wvalue;
2165         char *path;
2166         WERROR result = WERR_OK;
2167         NTSTATUS status;
2168         TALLOC_CTX *tmp_ctx;
2169
2170         tmp_ctx = talloc_new(mem_ctx);
2171         if (tmp_ctx == NULL) {
2172                 return WERR_NOMEM;
2173         }
2174
2175         path = winreg_printer_data_keyname(tmp_ctx, printer);
2176         if (path == NULL) {
2177                 TALLOC_FREE(tmp_ctx);
2178                 return WERR_NOMEM;
2179         }
2180
2181         ZERO_STRUCT(hive_hnd);
2182         ZERO_STRUCT(key_hnd);
2183
2184         DEBUG(8, ("winreg_set_printer_dataex: Open printer key %s, value %s, access_mask: 0x%05x for [%s]\n",
2185                         key, value, access_mask, printer));
2186         result = winreg_printer_openkey(tmp_ctx,
2187                                         server_info,
2188                                         &winreg_pipe,
2189                                         path,
2190                                         key,
2191                                         true,
2192                                         access_mask,
2193                                         &hive_hnd,
2194                                         &key_hnd);
2195         if (!W_ERROR_IS_OK(result)) {
2196                 DEBUG(0, ("winreg_set_printer_dataex: Could not open key %s: %s\n",
2197                           key, win_errstr(result)));
2198                 goto done;
2199         }
2200
2201         wvalue.name = value;
2202         status = rpccli_winreg_SetValue(winreg_pipe,
2203                                         tmp_ctx,
2204                                         &key_hnd,
2205                                         wvalue,
2206                                         type,
2207                                         data,
2208                                         data_size,
2209                                         &result);
2210         if (!NT_STATUS_IS_OK(status)) {
2211                 DEBUG(0, ("winreg_set_printer_dataex: Could not set value %s: %s\n",
2212                           value, nt_errstr(status)));
2213                 if (!W_ERROR_IS_OK(result)) {
2214                         goto done;
2215                 }
2216                 result = ntstatus_to_werror(status);
2217                 goto done;
2218         }
2219
2220         result = WERR_OK;
2221 done:
2222         if (winreg_pipe != NULL) {
2223                 if (is_valid_policy_hnd(&key_hnd)) {
2224                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2225                 }
2226                 if (is_valid_policy_hnd(&hive_hnd)) {
2227                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2228                 }
2229         }
2230
2231         TALLOC_FREE(tmp_ctx);
2232         return result;
2233 }
2234
2235 /* Get printer data over a winreg pipe. */
2236 WERROR winreg_get_printer_dataex(TALLOC_CTX *mem_ctx,
2237                                  struct auth_serversupplied_info *server_info,
2238                                  const char *printer,
2239                                  const char *key,
2240                                  const char *value,
2241                                  enum winreg_Type *type,
2242                                  uint8_t **data,
2243                                  uint32_t *data_size)
2244 {
2245         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2246         struct rpc_pipe_client *winreg_pipe = NULL;
2247         struct policy_handle hive_hnd, key_hnd;
2248         struct winreg_String wvalue;
2249         enum winreg_Type type_in;
2250         char *path;
2251         uint8_t *data_in;
2252         uint32_t data_in_size = 0;
2253         uint32_t value_len = 0;
2254         WERROR result = WERR_OK;
2255         NTSTATUS status;
2256         TALLOC_CTX *tmp_ctx;
2257
2258         tmp_ctx = talloc_new(mem_ctx);
2259         if (tmp_ctx == NULL) {
2260                 return WERR_NOMEM;
2261         }
2262
2263         path = winreg_printer_data_keyname(tmp_ctx, printer);
2264         if (path == NULL) {
2265                 TALLOC_FREE(tmp_ctx);
2266                 return WERR_NOMEM;
2267         }
2268
2269         ZERO_STRUCT(hive_hnd);
2270         ZERO_STRUCT(key_hnd);
2271
2272         result = winreg_printer_openkey(tmp_ctx,
2273                                         server_info,
2274                                         &winreg_pipe,
2275                                         path,
2276                                         key,
2277                                         false,
2278                                         access_mask,
2279                                         &hive_hnd,
2280                                         &key_hnd);
2281         if (!W_ERROR_IS_OK(result)) {
2282                 DEBUG(0, ("winreg_get_printer_dataex: Could not open key %s: %s\n",
2283                           key, win_errstr(result)));
2284                 goto done;
2285         }
2286
2287         wvalue.name = value;
2288
2289         /*
2290          * call QueryValue once with data == NULL to get the
2291          * needed memory size to be allocated, then allocate
2292          * data buffer and call again.
2293          */
2294         status = rpccli_winreg_QueryValue(winreg_pipe,
2295                                           tmp_ctx,
2296                                           &key_hnd,
2297                                           &wvalue,
2298                                           &type_in,
2299                                           NULL,
2300                                           &data_in_size,
2301                                           &value_len,
2302                                           &result);
2303         if (!NT_STATUS_IS_OK(status)) {
2304                 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2305                           value, nt_errstr(status)));
2306                 if (!W_ERROR_IS_OK(result)) {
2307                         goto done;
2308                 }
2309                 result = ntstatus_to_werror(status);
2310                 goto done;
2311         }
2312
2313         data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
2314         if (data_in == NULL) {
2315                 result = WERR_NOMEM;
2316                 goto done;
2317         }
2318         value_len = 0;
2319
2320         status = rpccli_winreg_QueryValue(winreg_pipe,
2321                                           tmp_ctx,
2322                                           &key_hnd,
2323                                           &wvalue,
2324                                           &type_in,
2325                                           data_in,
2326                                           &data_in_size,
2327                                           &value_len,
2328                                           &result);
2329         if (!NT_STATUS_IS_OK(status)) {
2330                 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2331                           value, nt_errstr(status)));
2332                 if (!W_ERROR_IS_OK(result)) {
2333                         result = ntstatus_to_werror(status);
2334                 }
2335                 goto done;
2336         }
2337
2338         *type = type_in;
2339         *data_size = data_in_size;
2340         if (data_in_size) {
2341                 *data = talloc_move(mem_ctx, &data_in);
2342         }
2343
2344         result = WERR_OK;
2345 done:
2346         if (winreg_pipe != NULL) {
2347                 if (is_valid_policy_hnd(&key_hnd)) {
2348                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2349                 }
2350                 if (is_valid_policy_hnd(&hive_hnd)) {
2351                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2352                 }
2353         }
2354
2355         TALLOC_FREE(tmp_ctx);
2356         return result;
2357 }
2358
2359 /* Enumerate on the values of a given key and provide the data. */
2360 WERROR winreg_enum_printer_dataex(TALLOC_CTX *mem_ctx,
2361                                   struct auth_serversupplied_info *server_info,
2362                                   const char *printer,
2363                                   const char *key,
2364                                   uint32_t *pnum_values,
2365                                   struct spoolss_PrinterEnumValues **penum_values)
2366 {
2367         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2368         struct rpc_pipe_client *winreg_pipe = NULL;
2369         struct policy_handle hive_hnd, key_hnd;
2370
2371         struct spoolss_PrinterEnumValues *enum_values = NULL;
2372         uint32_t num_values = 0;
2373         char *path;
2374         WERROR result = WERR_OK;
2375
2376         TALLOC_CTX *tmp_ctx;
2377
2378         tmp_ctx = talloc_new(mem_ctx);
2379         if (tmp_ctx == NULL) {
2380                 return WERR_NOMEM;
2381         }
2382
2383         path = winreg_printer_data_keyname(tmp_ctx, printer);
2384         if (path == NULL) {
2385                 TALLOC_FREE(tmp_ctx);
2386                 return WERR_NOMEM;
2387         }
2388
2389         result = winreg_printer_openkey(tmp_ctx,
2390                                         server_info,
2391                                         &winreg_pipe,
2392                                         path,
2393                                         key,
2394                                         false,
2395                                         access_mask,
2396                                         &hive_hnd,
2397                                         &key_hnd);
2398         if (!W_ERROR_IS_OK(result)) {
2399                 DEBUG(0, ("winreg_enum_printer_dataex: Could not open key %s: %s\n",
2400                           key, win_errstr(result)));
2401                 goto done;
2402         }
2403
2404         result = winreg_printer_enumvalues(tmp_ctx,
2405                                            winreg_pipe,
2406                                            &key_hnd,
2407                                            &num_values,
2408                                            &enum_values);
2409         if (!W_ERROR_IS_OK(result)) {
2410                 DEBUG(0, ("winreg_enum_printer_dataex: Could not enumerate values in %s: %s\n",
2411                           key, win_errstr(result)));
2412                 goto done;
2413         }
2414
2415         *pnum_values = num_values;
2416         if (penum_values) {
2417                 *penum_values = talloc_move(mem_ctx, &enum_values);
2418         }
2419
2420         result = WERR_OK;
2421 done:
2422         if (winreg_pipe != NULL) {
2423                 if (is_valid_policy_hnd(&key_hnd)) {
2424                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2425                 }
2426                 if (is_valid_policy_hnd(&hive_hnd)) {
2427                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2428                 }
2429         }
2430
2431         TALLOC_FREE(tmp_ctx);
2432         return result;
2433 }
2434
2435 /* Delete printer data over a winreg pipe. */
2436 WERROR winreg_delete_printer_dataex(TALLOC_CTX *mem_ctx,
2437                                     struct auth_serversupplied_info *server_info,
2438                                     const char *printer,
2439                                     const char *key,
2440                                     const char *value)
2441 {
2442         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2443         struct rpc_pipe_client *winreg_pipe = NULL;
2444         struct policy_handle hive_hnd, key_hnd;
2445         struct winreg_String wvalue;
2446         char *path;
2447         WERROR result = WERR_OK;
2448         NTSTATUS status;
2449
2450         TALLOC_CTX *tmp_ctx;
2451
2452         tmp_ctx = talloc_new(mem_ctx);
2453         if (tmp_ctx == NULL) {
2454                 return WERR_NOMEM;
2455         }
2456
2457         path = winreg_printer_data_keyname(tmp_ctx, printer);
2458         if (path == NULL) {
2459                 TALLOC_FREE(tmp_ctx);
2460                 return WERR_NOMEM;
2461         }
2462
2463         ZERO_STRUCT(hive_hnd);
2464         ZERO_STRUCT(key_hnd);
2465
2466         result = winreg_printer_openkey(tmp_ctx,
2467                                         server_info,
2468                                         &winreg_pipe,
2469                                         path,
2470                                         key,
2471                                         false,
2472                                         access_mask,
2473                                         &hive_hnd,
2474                                         &key_hnd);
2475         if (!W_ERROR_IS_OK(result)) {
2476                 DEBUG(0, ("winreg_delete_printer_dataex: Could not open key %s: %s\n",
2477                           key, win_errstr(result)));
2478                 goto done;
2479         }
2480
2481         wvalue.name = value;
2482         status = rpccli_winreg_DeleteValue(winreg_pipe,
2483                                            tmp_ctx,
2484                                            &key_hnd,
2485                                            wvalue,
2486                                            &result);
2487         if (!NT_STATUS_IS_OK(status)) {
2488                 DEBUG(0, ("winreg_delete_printer_dataex: Could not delete value %s: %s\n",
2489                           value, nt_errstr(status)));
2490                 if (!W_ERROR_IS_OK(result)) {
2491                         goto done;
2492                 }
2493                 result = ntstatus_to_werror(status);
2494                 goto done;
2495         }
2496
2497         result = WERR_OK;
2498 done:
2499         if (winreg_pipe != NULL) {
2500                 if (is_valid_policy_hnd(&key_hnd)) {
2501                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2502                 }
2503                 if (is_valid_policy_hnd(&hive_hnd)) {
2504                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2505                 }
2506         }
2507
2508         TALLOC_FREE(tmp_ctx);
2509         return result;
2510 }
2511
2512 /* Enumerate on the subkeys of a given key and provide the data. */
2513 WERROR winreg_enum_printer_key(TALLOC_CTX *mem_ctx,
2514                                struct auth_serversupplied_info *server_info,
2515                                const char *printer,
2516                                const char *key,
2517                                uint32_t *pnum_subkeys,
2518                                const char ***psubkeys)
2519 {
2520         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2521         struct rpc_pipe_client *winreg_pipe = NULL;
2522         struct policy_handle hive_hnd, key_hnd;
2523         char *path;
2524         const char **subkeys = NULL;
2525         uint32_t num_subkeys = -1;
2526
2527         WERROR result = WERR_OK;
2528
2529         TALLOC_CTX *tmp_ctx;
2530
2531         tmp_ctx = talloc_new(mem_ctx);
2532         if (tmp_ctx == NULL) {
2533                 return WERR_NOMEM;
2534         }
2535
2536         path = winreg_printer_data_keyname(tmp_ctx, printer);
2537         if (path == NULL) {
2538                 TALLOC_FREE(tmp_ctx);
2539                 return WERR_NOMEM;
2540         }
2541
2542         ZERO_STRUCT(hive_hnd);
2543         ZERO_STRUCT(key_hnd);
2544
2545         result = winreg_printer_openkey(tmp_ctx,
2546                                         server_info,
2547                                         &winreg_pipe,
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_enum_printer_key: Could not open key %s: %s\n",
2556                           key, win_errstr(result)));
2557                 goto done;
2558         }
2559
2560         result = winreg_printer_enumkeys(tmp_ctx,
2561                                          winreg_pipe,
2562                                          &key_hnd,
2563                                          &num_subkeys,
2564                                          &subkeys);
2565         if (!W_ERROR_IS_OK(result)) {
2566                 DEBUG(0, ("winreg_enum_printer_key: Could not enumerate subkeys in %s: %s\n",
2567                           key, win_errstr(result)));
2568                 goto done;
2569         }
2570
2571         *pnum_subkeys = num_subkeys;
2572         if (psubkeys) {
2573                 *psubkeys = talloc_move(mem_ctx, &subkeys);
2574         }
2575
2576         result = WERR_OK;
2577 done:
2578         if (winreg_pipe != NULL) {
2579                 if (is_valid_policy_hnd(&key_hnd)) {
2580                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2581                 }
2582                 if (is_valid_policy_hnd(&hive_hnd)) {
2583                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2584                 }
2585         }
2586
2587         TALLOC_FREE(tmp_ctx);
2588         return result;
2589 }
2590
2591 /* Delete a key with subkeys of a given printer. */
2592 WERROR winreg_delete_printer_key(TALLOC_CTX *mem_ctx,
2593                                  struct auth_serversupplied_info *server_info,
2594                                  const char *printer,
2595                                  const char *key)
2596 {
2597         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2598         struct rpc_pipe_client *winreg_pipe = NULL;
2599         struct policy_handle hive_hnd, key_hnd;
2600         char *keyname;
2601         char *path;
2602         WERROR result;
2603         TALLOC_CTX *tmp_ctx;
2604
2605         tmp_ctx = talloc_new(mem_ctx);
2606         if (tmp_ctx == NULL) {
2607                 return WERR_NOMEM;
2608         }
2609
2610         path = winreg_printer_data_keyname(tmp_ctx, printer);
2611         if (path == NULL) {
2612                 TALLOC_FREE(tmp_ctx);
2613                 return WERR_NOMEM;
2614         }
2615
2616         result = winreg_printer_openkey(tmp_ctx,
2617                                         server_info,
2618                                         &winreg_pipe,
2619                                         path,
2620                                         key,
2621                                         false,
2622                                         access_mask,
2623                                         &hive_hnd,
2624                                         &key_hnd);
2625         if (!W_ERROR_IS_OK(result)) {
2626                 /* key doesn't exist */
2627                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2628                         result = WERR_OK;
2629                         goto done;
2630                 }
2631
2632                 DEBUG(0, ("winreg_delete_printer_key: Could not open key %s: %s\n",
2633                           key, win_errstr(result)));
2634                 goto done;
2635         }
2636
2637         if (is_valid_policy_hnd(&key_hnd)) {
2638                 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2639         }
2640
2641         if (key == NULL || key[0] == '\0') {
2642                 keyname = path;
2643         } else {
2644                 keyname = talloc_asprintf(tmp_ctx,
2645                                           "%s\\%s",
2646                                           path,
2647                                           key);
2648                 if (keyname == NULL) {
2649                         result = WERR_NOMEM;
2650                         goto done;
2651                 }
2652         }
2653
2654         result = winreg_printer_delete_subkeys(tmp_ctx,
2655                                                winreg_pipe,
2656                                                &hive_hnd,
2657                                                access_mask,
2658                                                keyname);
2659         if (!W_ERROR_IS_OK(result)) {
2660                 DEBUG(0, ("winreg_delete_printer_key: Could not delete key %s: %s\n",
2661                           key, win_errstr(result)));
2662                 goto done;
2663         }
2664
2665 done:
2666         if (winreg_pipe != NULL) {
2667                 if (is_valid_policy_hnd(&key_hnd)) {
2668                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2669                 }
2670                 if (is_valid_policy_hnd(&hive_hnd)) {
2671                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2672                 }
2673         }
2674
2675         TALLOC_FREE(tmp_ctx);
2676         return result;
2677 }
2678
2679 WERROR winreg_printer_update_changeid(TALLOC_CTX *mem_ctx,
2680                                       struct auth_serversupplied_info *server_info,
2681                                       const char *printer)
2682 {
2683         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2684         struct rpc_pipe_client *winreg_pipe = NULL;
2685         struct policy_handle hive_hnd, key_hnd;
2686         char *path;
2687         WERROR result;
2688         TALLOC_CTX *tmp_ctx;
2689
2690         tmp_ctx = talloc_new(mem_ctx);
2691         if (tmp_ctx == NULL) {
2692                 return WERR_NOMEM;
2693         }
2694
2695         path = winreg_printer_data_keyname(tmp_ctx, printer);
2696         if (path == NULL) {
2697                 TALLOC_FREE(tmp_ctx);
2698                 return WERR_NOMEM;
2699         }
2700
2701         ZERO_STRUCT(hive_hnd);
2702         ZERO_STRUCT(key_hnd);
2703
2704         result = winreg_printer_openkey(tmp_ctx,
2705                                         server_info,
2706                                         &winreg_pipe,
2707                                         path,
2708                                         "",
2709                                         false,
2710                                         access_mask,
2711                                         &hive_hnd,
2712                                         &key_hnd);
2713         if (!W_ERROR_IS_OK(result)) {
2714                 DEBUG(0, ("winreg_printer_update_changeid: Could not open key %s: %s\n",
2715                           path, win_errstr(result)));
2716                 goto done;
2717         }
2718
2719         result = winreg_printer_write_dword(tmp_ctx,
2720                                             winreg_pipe,
2721                                             &key_hnd,
2722                                             "ChangeID",
2723                                             winreg_printer_rev_changeid());
2724         if (!W_ERROR_IS_OK(result)) {
2725                 goto done;
2726         }
2727
2728         result = WERR_OK;
2729 done:
2730         if (winreg_pipe != NULL) {
2731                 if (is_valid_policy_hnd(&key_hnd)) {
2732                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2733                 }
2734                 if (is_valid_policy_hnd(&hive_hnd)) {
2735                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2736                 }
2737         }
2738
2739         TALLOC_FREE(tmp_ctx);
2740         return result;
2741 }
2742
2743 WERROR winreg_printer_get_changeid(TALLOC_CTX *mem_ctx,
2744                                    struct auth_serversupplied_info *server_info,
2745                                    const char *printer,
2746                                    uint32_t *pchangeid)
2747 {
2748         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2749         struct rpc_pipe_client *winreg_pipe = NULL;
2750         struct policy_handle hive_hnd, key_hnd;
2751         uint32_t changeid = 0;
2752         char *path;
2753         WERROR result;
2754         TALLOC_CTX *tmp_ctx;
2755
2756         tmp_ctx = talloc_new(mem_ctx);
2757         if (tmp_ctx == NULL) {
2758                 return WERR_NOMEM;
2759         }
2760
2761         path = winreg_printer_data_keyname(tmp_ctx, printer);
2762         if (path == NULL) {
2763                 TALLOC_FREE(tmp_ctx);
2764                 return WERR_NOMEM;
2765         }
2766
2767         ZERO_STRUCT(hive_hnd);
2768         ZERO_STRUCT(key_hnd);
2769
2770         result = winreg_printer_openkey(tmp_ctx,
2771                                         server_info,
2772                                         &winreg_pipe,
2773                                         path,
2774                                         "",
2775                                         false,
2776                                         access_mask,
2777                                         &hive_hnd,
2778                                         &key_hnd);
2779         if (!W_ERROR_IS_OK(result)) {
2780                 DEBUG(0, ("winreg_printer_get_changeid: Could not open key %s: %s\n",
2781                           path, win_errstr(result)));
2782                 goto done;
2783         }
2784
2785         DEBUG(0, ("winreg_printer_get_changeid: get changeid from %s\n", path));
2786         result = winreg_printer_query_dword(tmp_ctx,
2787                                             winreg_pipe,
2788                                             &key_hnd,
2789                                             "ChangeID",
2790                                             &changeid);
2791         if (!W_ERROR_IS_OK(result)) {
2792                 goto done;
2793         }
2794
2795         if (pchangeid) {
2796                 *pchangeid = changeid;
2797         }
2798
2799         result = WERR_OK;
2800 done:
2801         if (winreg_pipe != NULL) {
2802                 if (is_valid_policy_hnd(&key_hnd)) {
2803                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2804                 }
2805                 if (is_valid_policy_hnd(&hive_hnd)) {
2806                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2807                 }
2808         }
2809
2810         TALLOC_FREE(tmp_ctx);
2811         return result;
2812 }
2813
2814 /*
2815  * The special behaviour of the spoolss forms is documented at the website:
2816  *
2817  * Managing Win32 Printserver Forms
2818  * http://unixwiz.net/techtips/winspooler-forms.html
2819  */
2820
2821 WERROR winreg_printer_addform1(TALLOC_CTX *mem_ctx,
2822                                struct auth_serversupplied_info *server_info,
2823                                struct spoolss_AddFormInfo1 *form)
2824 {
2825         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2826         struct rpc_pipe_client *winreg_pipe = NULL;
2827         struct policy_handle hive_hnd, key_hnd;
2828         struct winreg_String wvalue;
2829         DATA_BLOB blob;
2830         uint32_t num_info = 0;
2831         union spoolss_FormInfo *info = NULL;
2832         uint32_t i;
2833         WERROR result;
2834         NTSTATUS status;
2835         TALLOC_CTX *tmp_ctx;
2836
2837         tmp_ctx = talloc_new(mem_ctx);
2838         if (tmp_ctx == NULL) {
2839                 return WERR_NOMEM;
2840         }
2841
2842         ZERO_STRUCT(hive_hnd);
2843         ZERO_STRUCT(key_hnd);
2844
2845         result = winreg_printer_openkey(tmp_ctx,
2846                                         server_info,
2847                                         &winreg_pipe,
2848                                         TOP_LEVEL_CONTROL_FORMS_KEY,
2849                                         "",
2850                                         true,
2851                                         access_mask,
2852                                         &hive_hnd,
2853                                         &key_hnd);
2854         if (!W_ERROR_IS_OK(result)) {
2855                 DEBUG(0, ("winreg_printer_addform1: Could not open key %s: %s\n",
2856                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2857                 goto done;
2858         }
2859
2860         result = winreg_printer_enumforms1(tmp_ctx, server_info, &num_info, &info);
2861         if (!W_ERROR_IS_OK(result)) {
2862                 DEBUG(0, ("winreg_printer_addform: Could not enum keys %s: %s\n",
2863                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2864                 goto done;
2865         }
2866
2867         /* If form name already exists or is builtin return ALREADY_EXISTS */
2868         for (i = 0; i < num_info; i++) {
2869                 if (strequal(info[i].info1.form_name, form->form_name)) {
2870                         result = WERR_FILE_EXISTS;
2871                         goto done;
2872                 }
2873         }
2874
2875         wvalue.name = form->form_name;
2876
2877         blob = data_blob_talloc(tmp_ctx, NULL, 32);
2878         SIVAL(blob.data,  0, form->size.width);
2879         SIVAL(blob.data,  4, form->size.height);
2880         SIVAL(blob.data,  8, form->area.left);
2881         SIVAL(blob.data, 12, form->area.top);
2882         SIVAL(blob.data, 16, form->area.right);
2883         SIVAL(blob.data, 20, form->area.bottom);
2884         SIVAL(blob.data, 24, num_info + 1); /* FIXME */
2885         SIVAL(blob.data, 28, form->flags);
2886
2887         status = rpccli_winreg_SetValue(winreg_pipe,
2888                                         tmp_ctx,
2889                                         &key_hnd,
2890                                         wvalue,
2891                                         REG_BINARY,
2892                                         blob.data,
2893                                         blob.length,
2894                                         &result);
2895         if (!NT_STATUS_IS_OK(status)) {
2896                 DEBUG(0, ("winreg_printer_addform1: Could not set value %s: %s\n",
2897                           wvalue.name, nt_errstr(status)));
2898                 if (!W_ERROR_IS_OK(result)) {
2899                         goto done;
2900                 }
2901                 result = ntstatus_to_werror(status);
2902                 goto done;
2903         }
2904
2905         result = WERR_OK;
2906 done:
2907         if (winreg_pipe != NULL) {
2908                 if (is_valid_policy_hnd(&key_hnd)) {
2909                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2910                 }
2911                 if (is_valid_policy_hnd(&hive_hnd)) {
2912                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2913                 }
2914         }
2915
2916         TALLOC_FREE(info);
2917         TALLOC_FREE(tmp_ctx);
2918         return result;
2919 }
2920
2921 WERROR winreg_printer_enumforms1(TALLOC_CTX *mem_ctx,
2922                                  struct auth_serversupplied_info *server_info,
2923                                  uint32_t *pnum_info,
2924                                  union spoolss_FormInfo **pinfo)
2925 {
2926         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2927         struct rpc_pipe_client *winreg_pipe = NULL;
2928         struct policy_handle hive_hnd, key_hnd;
2929         union spoolss_FormInfo *info;
2930         struct spoolss_PrinterEnumValues *enum_values = NULL;
2931         uint32_t num_values = 0;
2932         uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
2933         uint32_t i;
2934         WERROR result;
2935         TALLOC_CTX *tmp_ctx;
2936
2937         tmp_ctx = talloc_new(mem_ctx);
2938         if (tmp_ctx == NULL) {
2939                 return WERR_NOMEM;
2940         }
2941
2942         ZERO_STRUCT(hive_hnd);
2943         ZERO_STRUCT(key_hnd);
2944
2945         result = winreg_printer_openkey(tmp_ctx,
2946                                         server_info,
2947                                         &winreg_pipe,
2948                                         TOP_LEVEL_CONTROL_FORMS_KEY,
2949                                         "",
2950                                         true,
2951                                         access_mask,
2952                                         &hive_hnd,
2953                                         &key_hnd);
2954         if (!W_ERROR_IS_OK(result)) {
2955                 /* key doesn't exist */
2956                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2957                         result = WERR_OK;
2958                         goto done;
2959                 }
2960
2961                 DEBUG(0, ("winreg_printer_enumforms1: Could not open key %s: %s\n",
2962                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2963                 goto done;
2964         }
2965
2966         result = winreg_printer_enumvalues(tmp_ctx,
2967                                            winreg_pipe,
2968                                            &key_hnd,
2969                                            &num_values,
2970                                            &enum_values);
2971         if (!W_ERROR_IS_OK(result)) {
2972                 DEBUG(0, ("winreg_printer_enumforms1: Could not enumerate values in %s: %s\n",
2973                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2974                 goto done;
2975         }
2976
2977         info = TALLOC_ARRAY(tmp_ctx, union spoolss_FormInfo, num_builtin + num_values);
2978         if (info == NULL) {
2979                 result = WERR_NOMEM;
2980                 goto done;
2981         }
2982
2983         /* Enumerate BUILTIN forms */
2984         for (i = 0; i < num_builtin; i++) {
2985                 info[i].info1 = builtin_forms1[i];
2986         }
2987
2988         /* Enumerate registry forms */
2989         for (i = 0; i < num_values; i++) {
2990                 union spoolss_FormInfo val;
2991
2992                 if (enum_values[i].type != REG_BINARY ||
2993                     enum_values[i].data_length != 32) {
2994                         continue;
2995                 }
2996
2997                 val.info1.form_name = talloc_strdup(info, enum_values[i].value_name);
2998                 if (val.info1.form_name == NULL) {
2999                         result = WERR_NOMEM;
3000                         goto done;
3001                 }
3002
3003                 val.info1.size.width  = IVAL(enum_values[i].data->data,  0);
3004                 val.info1.size.height = IVAL(enum_values[i].data->data,  4);
3005                 val.info1.area.left   = IVAL(enum_values[i].data->data,  8);
3006                 val.info1.area.top    = IVAL(enum_values[i].data->data, 12);
3007                 val.info1.area.right  = IVAL(enum_values[i].data->data, 16);
3008                 val.info1.area.bottom = IVAL(enum_values[i].data->data, 20);
3009                 /* skip form index      IVAL(enum_values[i].data->data, 24)));*/
3010                 val.info1.flags       = IVAL(enum_values[i].data->data, 28);
3011
3012                 info[i + num_builtin] = val;
3013         }
3014
3015         *pnum_info = num_builtin + num_values;
3016         if (pinfo) {
3017                 *pinfo = talloc_move(mem_ctx, &info);
3018         }
3019
3020 done:
3021         if (winreg_pipe != NULL) {
3022                 if (is_valid_policy_hnd(&key_hnd)) {
3023                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3024                 }
3025                 if (is_valid_policy_hnd(&hive_hnd)) {
3026                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
3027                 }
3028         }
3029
3030         TALLOC_FREE(enum_values);
3031         TALLOC_FREE(tmp_ctx);
3032         return result;
3033 }
3034
3035 WERROR winreg_printer_deleteform1(TALLOC_CTX *mem_ctx,
3036                                   struct auth_serversupplied_info *server_info,
3037                                   const char *form_name)
3038 {
3039         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3040         struct rpc_pipe_client *winreg_pipe = NULL;
3041         struct policy_handle hive_hnd, key_hnd;
3042         struct winreg_String wvalue;
3043         uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
3044         uint32_t i;
3045         WERROR result = WERR_OK;
3046         NTSTATUS status;
3047         TALLOC_CTX *tmp_ctx;
3048
3049         for (i = 0; i < num_builtin; i++) {
3050                 if (strequal(builtin_forms1[i].form_name, form_name)) {
3051                         return WERR_INVALID_PARAMETER;
3052                 }
3053         }
3054
3055         tmp_ctx = talloc_new(mem_ctx);
3056         if (tmp_ctx == NULL) {
3057                 return WERR_NOMEM;
3058         }
3059
3060         ZERO_STRUCT(hive_hnd);
3061         ZERO_STRUCT(key_hnd);
3062
3063         result = winreg_printer_openkey(tmp_ctx,
3064                                         server_info,
3065                                         &winreg_pipe,
3066                                         TOP_LEVEL_CONTROL_FORMS_KEY,
3067                                         "",
3068                                         false,
3069                                         access_mask,
3070                                         &hive_hnd,
3071                                         &key_hnd);
3072         if (!W_ERROR_IS_OK(result)) {
3073                 DEBUG(0, ("winreg_printer_deleteform1: Could not open key %s: %s\n",
3074                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3075                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
3076                         result = WERR_INVALID_FORM_NAME;
3077                 }
3078                 goto done;
3079         }
3080
3081         wvalue.name = form_name;
3082         status = rpccli_winreg_DeleteValue(winreg_pipe,
3083                                            tmp_ctx,
3084                                            &key_hnd,
3085                                            wvalue,
3086                                            &result);
3087         if (!NT_STATUS_IS_OK(status)) {
3088                 /* If the value doesn't exist, return WERR_INVALID_FORM_NAME */
3089                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
3090                         result = WERR_INVALID_FORM_NAME;
3091                         goto done;
3092                 }
3093                 DEBUG(0, ("winreg_printer_delteform1: Could not delete value %s: %s\n",
3094                           wvalue.name, nt_errstr(status)));
3095                 if (!W_ERROR_IS_OK(result)) {
3096                         goto done;
3097                 }
3098                 result = ntstatus_to_werror(status);
3099                 goto done;
3100         }
3101
3102         result = WERR_OK;
3103 done:
3104         if (winreg_pipe != NULL) {
3105                 if (is_valid_policy_hnd(&key_hnd)) {
3106                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3107                 }
3108                 if (is_valid_policy_hnd(&hive_hnd)) {
3109                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
3110                 }
3111         }
3112
3113         TALLOC_FREE(tmp_ctx);
3114         return result;
3115 }
3116
3117 WERROR winreg_printer_setform1(TALLOC_CTX *mem_ctx,
3118                                struct auth_serversupplied_info *server_info,
3119                                const char *form_name,
3120                                struct spoolss_AddFormInfo1 *form)
3121 {
3122         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3123         struct rpc_pipe_client *winreg_pipe = NULL;
3124         struct policy_handle hive_hnd, key_hnd;
3125         struct winreg_String wvalue;
3126         DATA_BLOB blob;
3127         uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
3128         uint32_t i;
3129         WERROR result;
3130         NTSTATUS status;
3131         TALLOC_CTX *tmp_ctx = NULL;
3132
3133         for (i = 0; i < num_builtin; i++) {
3134                 if (strequal(builtin_forms1[i].form_name, form->form_name)) {
3135                         result = WERR_INVALID_PARAM;
3136                         goto done;
3137                 }
3138         }
3139
3140         tmp_ctx = talloc_new(mem_ctx);
3141         if (tmp_ctx == NULL) {
3142                 return WERR_NOMEM;
3143         }
3144
3145         ZERO_STRUCT(hive_hnd);
3146         ZERO_STRUCT(key_hnd);
3147
3148         result = winreg_printer_openkey(tmp_ctx,
3149                                         server_info,
3150                                         &winreg_pipe,
3151                                         TOP_LEVEL_CONTROL_FORMS_KEY,
3152                                         "",
3153                                         true,
3154                                         access_mask,
3155                                         &hive_hnd,
3156                                         &key_hnd);
3157         if (!W_ERROR_IS_OK(result)) {
3158                 DEBUG(0, ("winreg_printer_setform1: Could not open key %s: %s\n",
3159                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3160                 goto done;
3161         }
3162
3163         /* If form_name != form->form_name then we renamed the form */
3164         if (strequal(form_name, form->form_name)) {
3165                 result = winreg_printer_deleteform1(tmp_ctx, server_info, form_name);
3166                 if (!W_ERROR_IS_OK(result)) {
3167                         DEBUG(0, ("winreg_printer_setform1: Could not open key %s: %s\n",
3168                                   TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3169                         goto done;
3170                 }
3171         }
3172
3173         wvalue.name = form->form_name;
3174
3175         blob = data_blob_talloc(tmp_ctx, NULL, 32);
3176         SIVAL(blob.data,  0, form->size.width);
3177         SIVAL(blob.data,  4, form->size.height);
3178         SIVAL(blob.data,  8, form->area.left);
3179         SIVAL(blob.data, 12, form->area.top);
3180         SIVAL(blob.data, 16, form->area.right);
3181         SIVAL(blob.data, 20, form->area.bottom);
3182         SIVAL(blob.data, 24, 42);
3183         SIVAL(blob.data, 28, form->flags);
3184
3185         status = rpccli_winreg_SetValue(winreg_pipe,
3186                                         tmp_ctx,
3187                                         &key_hnd,
3188                                         wvalue,
3189                                         REG_BINARY,
3190                                         blob.data,
3191                                         blob.length,
3192                                         &result);
3193         if (!NT_STATUS_IS_OK(status)) {
3194                 DEBUG(0, ("winreg_printer_setform1: Could not set value %s: %s\n",
3195                           wvalue.name, nt_errstr(status)));
3196                 if (!W_ERROR_IS_OK(result)) {
3197                         goto done;
3198                 }
3199                 result = ntstatus_to_werror(status);
3200                 goto done;
3201         }
3202
3203         result = WERR_OK;
3204 done:
3205         if (winreg_pipe != NULL) {
3206                 if (is_valid_policy_hnd(&key_hnd)) {
3207                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3208                 }
3209                 if (is_valid_policy_hnd(&hive_hnd)) {
3210                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
3211                 }
3212         }
3213
3214         TALLOC_FREE(tmp_ctx);
3215         return result;
3216 }
3217
3218 WERROR winreg_printer_getform1(TALLOC_CTX *mem_ctx,
3219                                struct auth_serversupplied_info *server_info,
3220                                const char *form_name,
3221                                struct spoolss_FormInfo1 *r)
3222 {
3223         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3224         struct rpc_pipe_client *winreg_pipe = NULL;
3225         struct policy_handle hive_hnd, key_hnd;
3226         struct winreg_String wvalue;
3227         enum winreg_Type type_in;
3228         uint8_t *data_in;
3229         uint32_t data_in_size = 0;
3230         uint32_t value_len = 0;
3231         uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
3232         uint32_t i;
3233         WERROR result;
3234         NTSTATUS status;
3235         TALLOC_CTX *tmp_ctx;
3236
3237         /* check builtin forms first */
3238         for (i = 0; i < num_builtin; i++) {
3239                 if (strequal(builtin_forms1[i].form_name, form_name)) {
3240                         *r = builtin_forms1[i];
3241                         return WERR_OK;
3242                 }
3243         }
3244
3245         tmp_ctx = talloc_new(mem_ctx);
3246         if (tmp_ctx == NULL) {
3247                 return WERR_NOMEM;
3248         }
3249
3250         ZERO_STRUCT(hive_hnd);
3251         ZERO_STRUCT(key_hnd);
3252
3253         result = winreg_printer_openkey(tmp_ctx,
3254                                         server_info,
3255                                         &winreg_pipe,
3256                                         TOP_LEVEL_CONTROL_FORMS_KEY,
3257                                         "",
3258                                         true,
3259                                         access_mask,
3260                                         &hive_hnd,
3261                                         &key_hnd);
3262         if (!W_ERROR_IS_OK(result)) {
3263                 DEBUG(0, ("winreg_printer_getform1: Could not open key %s: %s\n",
3264                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3265                 goto done;
3266         }
3267
3268         wvalue.name = form_name;
3269
3270         /*
3271          * call QueryValue once with data == NULL to get the
3272          * needed memory size to be allocated, then allocate
3273          * data buffer and call again.
3274          */
3275         status = rpccli_winreg_QueryValue(winreg_pipe,
3276                                           tmp_ctx,
3277                                           &key_hnd,
3278                                           &wvalue,
3279                                           &type_in,
3280                                           NULL,
3281                                           &data_in_size,
3282                                           &value_len,
3283                                           &result);
3284         if (!NT_STATUS_IS_OK(status)) {
3285                 DEBUG(0, ("winreg_printer_getform1: Could not query value %s: %s\n",
3286                           wvalue.name, nt_errstr(status)));
3287                 if (!W_ERROR_IS_OK(result)) {
3288                         goto done;
3289                 }
3290                 result = ntstatus_to_werror(status);
3291                 goto done;
3292         }
3293
3294         data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
3295         if (data_in == NULL) {
3296                 result = WERR_NOMEM;
3297                 goto done;
3298         }
3299         value_len = 0;
3300
3301         status = rpccli_winreg_QueryValue(winreg_pipe,
3302                                           tmp_ctx,
3303                                           &key_hnd,
3304                                           &wvalue,
3305                                           &type_in,
3306                                           data_in,
3307                                           &data_in_size,
3308                                           &value_len,
3309                                           &result);
3310         if (!NT_STATUS_IS_OK(status)) {
3311                 DEBUG(0, ("winreg_printer_getform1: Could not query value %s: %s\n",
3312                           wvalue.name, nt_errstr(status)));
3313                 if (!W_ERROR_IS_OK(result)) {
3314                         goto done;
3315                 }
3316                 result = ntstatus_to_werror(status);
3317                 goto done;
3318         }
3319
3320         r->form_name = talloc_strdup(mem_ctx, form_name);
3321         if (r->form_name == NULL) {
3322                 result = WERR_NOMEM;
3323                 goto done;
3324         }
3325
3326         r->size.width  = IVAL(data_in,  0);
3327         r->size.height = IVAL(data_in,  4);
3328         r->area.left   = IVAL(data_in,  8);
3329         r->area.top    = IVAL(data_in, 12);
3330         r->area.right  = IVAL(data_in, 16);
3331         r->area.bottom = IVAL(data_in, 20);
3332         /* skip index    IVAL(data_in, 24)));*/
3333         r->flags       = IVAL(data_in, 28);
3334
3335         result = WERR_OK;
3336 done:
3337         if (winreg_pipe != NULL) {
3338                 if (is_valid_policy_hnd(&key_hnd)) {
3339                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3340                 }
3341                 if (is_valid_policy_hnd(&hive_hnd)) {
3342                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
3343                 }
3344         }
3345
3346         TALLOC_FREE(tmp_ctx);
3347         return result;
3348 }
3349
3350 WERROR winreg_add_driver(TALLOC_CTX *mem_ctx,
3351                          struct auth_serversupplied_info *server_info,
3352                          struct spoolss_AddDriverInfoCtr *r,
3353                          const char **driver_name,
3354                          uint32_t *driver_version)
3355 {
3356         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3357         struct rpc_pipe_client *winreg_pipe = NULL;
3358         struct policy_handle hive_hnd, key_hnd;
3359         struct spoolss_DriverInfo8 info8;
3360         TALLOC_CTX *tmp_ctx = NULL;
3361         WERROR result;
3362
3363         ZERO_STRUCT(hive_hnd);
3364         ZERO_STRUCT(key_hnd);
3365         ZERO_STRUCT(info8);
3366
3367         if (!driver_info_ctr_to_info8(r, &info8)) {
3368                 result = WERR_INVALID_PARAMETER;
3369                 goto done;
3370         }
3371
3372         tmp_ctx = talloc_new(mem_ctx);
3373         if (tmp_ctx == NULL) {
3374                 return WERR_NOMEM;
3375         }
3376
3377         result = winreg_printer_opendriver(tmp_ctx,
3378                                            server_info,
3379                                            info8.driver_name,
3380                                            info8.architecture,
3381                                            info8.version,
3382                                            access_mask, true,
3383                                            &winreg_pipe,
3384                                            &hive_hnd,
3385                                            &key_hnd);
3386         if (!W_ERROR_IS_OK(result)) {
3387                 DEBUG(0, ("winreg_add_driver: "
3388                           "Could not open driver key (%s,%s,%d): %s\n",
3389                           info8.driver_name, info8.architecture,
3390                           info8.version, win_errstr(result)));
3391                 goto done;
3392         }
3393
3394         /* TODO: "Attributes" ? */
3395
3396         result = winreg_printer_write_dword(tmp_ctx, winreg_pipe,
3397                                             &key_hnd, "Version",
3398                                             info8.version);
3399         if (!W_ERROR_IS_OK(result)) {
3400                 goto done;
3401         }
3402
3403         result = winreg_printer_write_sz(tmp_ctx, winreg_pipe,
3404                                          &key_hnd, "Driver",
3405                                          info8.driver_path);
3406         if (!W_ERROR_IS_OK(result)) {
3407                 goto done;
3408         }
3409
3410         result = winreg_printer_write_sz(tmp_ctx, winreg_pipe,
3411                                          &key_hnd, "Data File",
3412                                          info8.data_file);
3413         if (!W_ERROR_IS_OK(result)) {
3414                 goto done;
3415         }
3416
3417         result = winreg_printer_write_sz(tmp_ctx, winreg_pipe,
3418                                          &key_hnd, "Configuration File",
3419                                          info8.config_file);
3420         if (!W_ERROR_IS_OK(result)) {
3421                 goto done;
3422         }
3423
3424         result = winreg_printer_write_sz(tmp_ctx, winreg_pipe,
3425                                          &key_hnd, "Help File",
3426                                          info8.help_file);
3427         if (!W_ERROR_IS_OK(result)) {
3428                 goto done;
3429         }
3430
3431         result = winreg_printer_write_multi_sz(tmp_ctx, winreg_pipe,
3432                                                &key_hnd, "Dependent Files",
3433                                                info8.dependent_files);
3434         if (!W_ERROR_IS_OK(result)) {
3435                 goto done;
3436         }
3437
3438         result = winreg_printer_write_sz(tmp_ctx, winreg_pipe,
3439                                          &key_hnd, "Monitor",
3440                                          info8.monitor_name);
3441         if (!W_ERROR_IS_OK(result)) {
3442                 goto done;
3443         }
3444
3445         result = winreg_printer_write_sz(tmp_ctx, winreg_pipe,
3446                                          &key_hnd, "Datatype",
3447                                          info8.default_datatype);
3448         if (!W_ERROR_IS_OK(result)) {
3449                 goto done;
3450         }
3451
3452         result = winreg_printer_write_multi_sz(tmp_ctx, winreg_pipe,
3453                                                &key_hnd, "Previous Names",
3454                                                info8.previous_names);
3455         if (!W_ERROR_IS_OK(result)) {
3456                 goto done;
3457         }
3458
3459         result = winreg_printer_write_date(tmp_ctx, winreg_pipe,
3460                                            &key_hnd, "DriverDate",
3461                                            info8.driver_date);
3462         if (!W_ERROR_IS_OK(result)) {
3463                 goto done;
3464         }
3465
3466         result = winreg_printer_write_ver(tmp_ctx, winreg_pipe,
3467                                           &key_hnd, "DriverVersion",
3468                                           info8.driver_version);
3469         if (!W_ERROR_IS_OK(result)) {
3470                 goto done;
3471         }
3472
3473         result = winreg_printer_write_sz(tmp_ctx, winreg_pipe,
3474                                          &key_hnd, "Manufacturer",
3475                                          info8.manufacturer_name);
3476         if (!W_ERROR_IS_OK(result)) {
3477                 goto done;
3478         }
3479
3480         result = winreg_printer_write_sz(tmp_ctx, winreg_pipe,
3481                                          &key_hnd, "OEM URL",
3482                                          info8.manufacturer_url);
3483         if (!W_ERROR_IS_OK(result)) {
3484                 goto done;
3485         }
3486
3487         result = winreg_printer_write_sz(tmp_ctx, winreg_pipe,
3488                                          &key_hnd, "HardwareID",
3489                                          info8.hardware_id);
3490         if (!W_ERROR_IS_OK(result)) {
3491                 goto done;
3492         }
3493
3494         result = winreg_printer_write_sz(tmp_ctx, winreg_pipe,
3495                                          &key_hnd, "Provider",
3496                                          info8.provider);
3497         if (!W_ERROR_IS_OK(result)) {
3498                 goto done;
3499         }
3500
3501         result = winreg_printer_write_sz(tmp_ctx, winreg_pipe,
3502                                          &key_hnd, "Print Processor",
3503                                          info8.print_processor);
3504         if (!W_ERROR_IS_OK(result)) {
3505                 goto done;
3506         }
3507
3508         result = winreg_printer_write_sz(tmp_ctx, winreg_pipe,
3509                                          &key_hnd, "VendorSetup",
3510                                          info8.vendor_setup);
3511         if (!W_ERROR_IS_OK(result)) {
3512                 goto done;
3513         }
3514
3515         result = winreg_printer_write_multi_sz(tmp_ctx, winreg_pipe,
3516                                                &key_hnd, "Color Profiles",
3517                                                info8.color_profiles);
3518         if (!W_ERROR_IS_OK(result)) {
3519                 goto done;
3520         }
3521
3522         result = winreg_printer_write_sz(tmp_ctx, winreg_pipe,
3523                                          &key_hnd, "InfPath",
3524                                          info8.inf_path);
3525         if (!W_ERROR_IS_OK(result)) {
3526                 goto done;
3527         }
3528
3529         result = winreg_printer_write_dword(tmp_ctx, winreg_pipe, &key_hnd,
3530                                             "PrinterDriverAttributes",
3531                                             info8.printer_driver_attributes);
3532         if (!W_ERROR_IS_OK(result)) {
3533                 goto done;
3534         }
3535
3536         result = winreg_printer_write_multi_sz(tmp_ctx, winreg_pipe,
3537                                                &key_hnd, "CoreDependencies",
3538                                                info8.core_driver_dependencies);
3539         if (!W_ERROR_IS_OK(result)) {
3540                 goto done;
3541         }
3542
3543         result = winreg_printer_write_date(tmp_ctx, winreg_pipe,
3544                                            &key_hnd, "MinInboxDriverVerDate",
3545                                            info8.min_inbox_driver_ver_date);
3546         if (!W_ERROR_IS_OK(result)) {
3547                 goto done;
3548         }
3549
3550         result = winreg_printer_write_ver(tmp_ctx, winreg_pipe, &key_hnd,
3551                                           "MinInboxDriverVerVersion",
3552                                           info8.min_inbox_driver_ver_version);
3553         if (!W_ERROR_IS_OK(result)) {
3554                 goto done;
3555         }
3556
3557         *driver_name = info8.driver_name;
3558         *driver_version = info8.version;
3559         result = WERR_OK;
3560 done:
3561         if (winreg_pipe != NULL) {
3562                 if (is_valid_policy_hnd(&key_hnd)) {
3563                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3564                 }
3565                 if (is_valid_policy_hnd(&hive_hnd)) {
3566                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
3567                 }
3568         }
3569
3570         TALLOC_FREE(tmp_ctx);
3571         return result;
3572 }
3573
3574 WERROR winreg_get_driver(TALLOC_CTX *mem_ctx,
3575                          struct auth_serversupplied_info *server_info,
3576                          const char *architecture,
3577                          const char *driver_name,
3578                          uint32_t driver_version,
3579                          struct spoolss_DriverInfo8 **_info8)
3580 {
3581         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3582         struct rpc_pipe_client *winreg_pipe = NULL;
3583         struct policy_handle hive_hnd, key_hnd;
3584         struct spoolss_DriverInfo8 i8, *info8;
3585         struct spoolss_PrinterEnumValues *enum_values = NULL;
3586         struct spoolss_PrinterEnumValues *v;
3587         uint32_t num_values = 0;
3588         TALLOC_CTX *tmp_ctx;
3589         WERROR result;
3590         uint32_t i;
3591
3592         ZERO_STRUCT(hive_hnd);
3593         ZERO_STRUCT(key_hnd);
3594         ZERO_STRUCT(i8);
3595
3596         tmp_ctx = talloc_new(mem_ctx);
3597         if (tmp_ctx == NULL) {
3598                 return WERR_NOMEM;
3599         }
3600
3601         if (driver_version == DRIVER_ANY_VERSION) {
3602                 /* look for Win2k first and then for NT4 */
3603                 result = winreg_printer_opendriver(tmp_ctx,
3604                                                    server_info,
3605                                                    driver_name,
3606                                                    architecture,
3607                                                    3,
3608                                                    access_mask, false,
3609                                                    &winreg_pipe,
3610                                                    &hive_hnd,
3611                                                    &key_hnd);
3612                 if (!W_ERROR_IS_OK(result)) {
3613                         result = winreg_printer_opendriver(tmp_ctx,
3614                                                            server_info,
3615                                                            driver_name,
3616                                                            architecture,
3617                                                            2,
3618                                                            access_mask, false,
3619                                                            &winreg_pipe,
3620                                                            &hive_hnd,
3621                                                            &key_hnd);
3622                 }
3623         } else {
3624                 /* ok normal case */
3625                 result = winreg_printer_opendriver(tmp_ctx,
3626                                                    server_info,
3627                                                    driver_name,
3628                                                    architecture,
3629                                                    driver_version,
3630                                                    access_mask, false,
3631                                                    &winreg_pipe,
3632                                                    &hive_hnd,
3633                                                    &key_hnd);
3634         }
3635         if (!W_ERROR_IS_OK(result)) {
3636                 DEBUG(5, ("winreg_get_driver: "
3637                           "Could not open driver key (%s,%s,%d): %s\n",
3638                           driver_name, architecture,
3639                           driver_version, win_errstr(result)));
3640                 goto done;
3641         }
3642
3643         result = winreg_printer_enumvalues(tmp_ctx,
3644                                            winreg_pipe,
3645                                            &key_hnd,
3646                                            &num_values,
3647                                            &enum_values);
3648         if (!W_ERROR_IS_OK(result)) {
3649                 DEBUG(0, ("winreg_get_driver: "
3650                           "Could not enumerate values for (%s,%s,%d): %s\n",
3651                           driver_name, architecture,
3652                           driver_version, win_errstr(result)));
3653                 goto done;
3654         }
3655
3656         info8 = talloc_zero(tmp_ctx, struct spoolss_DriverInfo8);
3657         if (!info8) {
3658                 result = WERR_NOMEM;
3659                 goto done;
3660         }
3661
3662         result = WERR_OK;
3663
3664         for (i = 0; i < num_values; i++) {
3665                 const char *tmp_str;
3666
3667                 v = &enum_values[i];
3668
3669                 result = winreg_enumval_to_dword(info8, v,
3670                                                  "Version",
3671                                                  &info8->version);
3672                 CHECK_ERROR(result);
3673
3674                 result = winreg_enumval_to_sz(info8, v,
3675                                               "Driver",
3676                                               &info8->driver_path);
3677                 CHECK_ERROR(result);
3678
3679                 result = winreg_enumval_to_sz(info8, v,
3680                                               "Data File",
3681                                               &info8->data_file);
3682                 CHECK_ERROR(result);
3683
3684                 result = winreg_enumval_to_sz(info8, v,
3685                                               "Configuration File",
3686                                               &info8->config_file);
3687                 CHECK_ERROR(result);
3688
3689                 result = winreg_enumval_to_sz(info8, v,
3690                                               "Help File",
3691                                               &info8->help_file);
3692                 CHECK_ERROR(result);
3693
3694                 result = winreg_enumval_to_multi_sz(info8, v,
3695                                                     "Dependent Files",
3696                                                     &info8->dependent_files);
3697                 CHECK_ERROR(result);
3698
3699                 result = winreg_enumval_to_sz(info8, v,
3700                                               "Monitor",
3701                                               &info8->monitor_name);
3702                 CHECK_ERROR(result);
3703
3704                 result = winreg_enumval_to_sz(info8, v,
3705                                               "Datatype",
3706                                               &info8->default_datatype);
3707                 CHECK_ERROR(result);
3708
3709                 result = winreg_enumval_to_multi_sz(info8, v,
3710                                                     "Previous Names",
3711                                                     &info8->previous_names);
3712                 CHECK_ERROR(result);
3713
3714                 result = winreg_enumval_to_sz(info8, v,
3715                                               "DriverDate",
3716                                               &tmp_str);
3717                 if (W_ERROR_IS_OK(result)) {
3718                         result = winreg_printer_date_to_NTTIME(tmp_str,
3719                                                 &info8->driver_date);
3720                 }
3721                 CHECK_ERROR(result);
3722
3723                 result = winreg_enumval_to_sz(info8, v,
3724                                               "DriverVersion",
3725                                               &tmp_str);
3726                 if (W_ERROR_IS_OK(result)) {
3727                         result = winreg_printer_ver_to_dword(tmp_str,
3728                                                 &info8->driver_version);
3729                 }
3730                 CHECK_ERROR(result);
3731
3732                 result = winreg_enumval_to_sz(info8, v,
3733                                               "Manufacturer",
3734                                               &info8->manufacturer_name);
3735                 CHECK_ERROR(result);
3736
3737                 result = winreg_enumval_to_sz(info8, v,
3738                                               "OEM URL",
3739                                               &info8->manufacturer_url);
3740                 CHECK_ERROR(result);
3741
3742                 result = winreg_enumval_to_sz(info8, v,
3743                                               "HardwareID",
3744                                               &info8->hardware_id);
3745                 CHECK_ERROR(result);
3746
3747                 result = winreg_enumval_to_sz(info8, v,
3748                                               "Provider",
3749                                               &info8->provider);
3750                 CHECK_ERROR(result);
3751
3752                 result = winreg_enumval_to_sz(info8, v,
3753                                               "Print Processor",
3754                                               &info8->print_processor);
3755                 CHECK_ERROR(result);
3756
3757                 result = winreg_enumval_to_sz(info8, v,
3758                                               "VendorSetup",
3759                                               &info8->vendor_setup);
3760                 CHECK_ERROR(result);
3761
3762                 result = winreg_enumval_to_multi_sz(info8, v,
3763                                                     "Color Profiles",
3764                                                     &info8->color_profiles);
3765                 CHECK_ERROR(result);
3766
3767                 result = winreg_enumval_to_sz(info8, v,
3768                                               "InfPath",
3769                                               &info8->inf_path);
3770                 CHECK_ERROR(result);
3771
3772                 result = winreg_enumval_to_dword(info8, v,
3773                                                  "PrinterDriverAttributes",
3774                                                  &info8->printer_driver_attributes);
3775                 CHECK_ERROR(result);
3776
3777                 result = winreg_enumval_to_multi_sz(info8, v,
3778                                                     "CoreDependencies",
3779                                                     &info8->core_driver_dependencies);
3780                 CHECK_ERROR(result);
3781
3782                 result = winreg_enumval_to_sz(info8, v,
3783                                               "MinInboxDriverVerDate",
3784                                               &tmp_str);
3785                 if (W_ERROR_IS_OK(result)) {
3786                         result = winreg_printer_date_to_NTTIME(tmp_str,
3787                                         &info8->min_inbox_driver_ver_date);
3788                 }
3789                 CHECK_ERROR(result);
3790
3791                 result = winreg_enumval_to_sz(info8, v,
3792                                               "MinInboxDriverVerVersion",
3793                                               &tmp_str);
3794                 if (W_ERROR_IS_OK(result)) {
3795                         result = winreg_printer_ver_to_dword(tmp_str,
3796                                         &info8->min_inbox_driver_ver_version);
3797                 }
3798                 CHECK_ERROR(result);
3799         }
3800
3801         if (!W_ERROR_IS_OK(result)) {
3802                 DEBUG(0, ("winreg_enumval_to_TYPE() failed "
3803                           "for %s: %s\n", v->value_name,
3804                           win_errstr(result)));
3805                 goto done;
3806         }
3807
3808         *_info8 = talloc_steal(mem_ctx, info8);
3809         result = WERR_OK;
3810 done:
3811         if (winreg_pipe != NULL) {
3812                 if (is_valid_policy_hnd(&key_hnd)) {
3813                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3814                 }
3815                 if (is_valid_policy_hnd(&hive_hnd)) {
3816                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
3817                 }
3818         }
3819
3820         TALLOC_FREE(tmp_ctx);
3821         return result;
3822 }
3823
3824 WERROR winreg_del_driver(TALLOC_CTX *mem_ctx,
3825                          struct auth_serversupplied_info *server_info,
3826                          struct spoolss_DriverInfo8 *info8,
3827                          uint32_t version)
3828 {
3829         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3830         struct rpc_pipe_client *winreg_pipe = NULL;
3831         struct policy_handle hive_hnd, key_hnd;
3832         TALLOC_CTX *tmp_ctx;
3833         char *key_name;
3834         WERROR result;
3835
3836         ZERO_STRUCT(hive_hnd);
3837         ZERO_STRUCT(key_hnd);
3838
3839         tmp_ctx = talloc_new(mem_ctx);
3840         if (tmp_ctx == NULL) {
3841                 return WERR_NOMEM;
3842         }
3843
3844         /* test that the key exists */
3845         result = winreg_printer_opendriver(tmp_ctx,
3846                                            server_info,
3847                                            info8->driver_name,
3848                                            info8->architecture,
3849                                            version,
3850                                            access_mask, false,
3851                                            &winreg_pipe,
3852                                            &hive_hnd,
3853                                            &key_hnd);
3854         if (!W_ERROR_IS_OK(result)) {
3855                 /* key doesn't exist */
3856                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
3857                         result = WERR_OK;
3858                         goto done;
3859                 }
3860
3861                 DEBUG(5, ("winreg_del_driver: "
3862                           "Could not open driver (%s,%s,%u): %s\n",
3863                           info8->driver_name, info8->architecture,
3864                           version, win_errstr(result)));
3865                 goto done;
3866         }
3867
3868
3869         if (is_valid_policy_hnd(&key_hnd)) {
3870                 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3871         }
3872
3873         key_name = talloc_asprintf(tmp_ctx,
3874                                    "%s\\Environments\\%s\\Drivers\\Version-%u",
3875                                    TOP_LEVEL_CONTROL_KEY,
3876                                    info8->architecture, version);
3877         if (key_name == NULL) {
3878                 result = WERR_NOMEM;
3879                 goto done;
3880         }
3881
3882         result = winreg_printer_delete_subkeys(tmp_ctx,
3883                                                winreg_pipe,
3884                                                &hive_hnd,
3885                                                access_mask,
3886                                                key_name);
3887         if (!W_ERROR_IS_OK(result)) {
3888                 DEBUG(0, ("winreg_del_driver: "
3889                           "Could not open driver (%s,%s,%u): %s\n",
3890                           info8->driver_name, info8->architecture,
3891                           version, win_errstr(result)));
3892                 goto done;
3893         }
3894
3895         result = WERR_OK;
3896 done:
3897         if (winreg_pipe != NULL) {
3898                 if (is_valid_policy_hnd(&key_hnd)) {
3899                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3900                 }
3901                 if (is_valid_policy_hnd(&hive_hnd)) {
3902                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
3903                 }
3904         }
3905
3906         TALLOC_FREE(tmp_ctx);
3907         return result;
3908 }
3909
3910 WERROR winreg_get_driver_list(TALLOC_CTX *mem_ctx,
3911                               struct auth_serversupplied_info *server_info,
3912                               const char *architecture,
3913                               uint32_t version,
3914                               uint32_t *num_drivers,
3915                               const char ***drivers)
3916 {
3917         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3918         struct rpc_pipe_client *winreg_pipe = NULL;
3919         struct policy_handle hive_hnd, key_hnd;
3920         TALLOC_CTX *tmp_ctx;
3921         WERROR result;
3922
3923         ZERO_STRUCT(hive_hnd);
3924         ZERO_STRUCT(key_hnd);
3925
3926         tmp_ctx = talloc_new(mem_ctx);
3927         if (tmp_ctx == NULL) {
3928                 return WERR_NOMEM;
3929         }
3930
3931         /* use NULL for the driver name so we open the key that is
3932          * parent of all drivers for this architecture and version */
3933         result = winreg_printer_opendriver(tmp_ctx,
3934                                            server_info,
3935                                            NULL,
3936                                            architecture,
3937                                            version,
3938                                            access_mask, false,
3939                                            &winreg_pipe,
3940                                            &hive_hnd,
3941                                            &key_hnd);
3942         if (!W_ERROR_IS_OK(result)) {
3943                 DEBUG(5, ("winreg_get_driver_list: "
3944                           "Could not open key (%s,%u): %s\n",
3945                           architecture, version, win_errstr(result)));
3946                 goto done;
3947         }
3948
3949         result = winreg_printer_enumkeys(tmp_ctx,
3950                                          winreg_pipe,
3951                                          &key_hnd,
3952                                          num_drivers,
3953                                          drivers);
3954         if (!W_ERROR_IS_OK(result)) {
3955                 DEBUG(0, ("winreg_get_driver_list: "
3956                           "Could not enumerate drivers for (%s,%u): %s\n",
3957                           architecture, version, win_errstr(result)));
3958                 goto done;
3959         }
3960
3961         result = WERR_OK;
3962 done:
3963         if (winreg_pipe != NULL) {
3964                 if (is_valid_policy_hnd(&key_hnd)) {
3965                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3966                 }
3967                 if (is_valid_policy_hnd(&hive_hnd)) {
3968                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
3969                 }
3970         }
3971
3972         TALLOC_FREE(tmp_ctx);
3973         return result;
3974 }
3975