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