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