6a96cb90b54fbd9c0bd8bd24531963ebd1230436
[ira/wip.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                 result = winreg_set_printer_secdesc(tmp_ctx,
1783                                                     server_info,
1784                                                     sharename,
1785                                                     secdesc);
1786                 if (!W_ERROR_IS_OK(result)) {
1787                         goto done;
1788                 }
1789         }
1790
1791         if (info2_mask & SPOOLSS_PRINTER_INFO_SEPFILE) {
1792                 result = winreg_printer_write_sz(tmp_ctx,
1793                                                  winreg_pipe,
1794                                                  &key_hnd,
1795                                                  "Separator File",
1796                                                  info2->sepfile);
1797                 if (!W_ERROR_IS_OK(result)) {
1798                         goto done;
1799                 }
1800         }
1801
1802         if (info2_mask & SPOOLSS_PRINTER_INFO_SHARENAME) {
1803                 result = winreg_printer_write_sz(tmp_ctx,
1804                                                  winreg_pipe,
1805                                                  &key_hnd,
1806                                                  "Share Name",
1807                                                  info2->sharename);
1808                 if (!W_ERROR_IS_OK(result)) {
1809                         goto done;
1810                 }
1811         }
1812
1813         if (info2_mask & SPOOLSS_PRINTER_INFO_STARTTIME) {
1814                 result = winreg_printer_write_dword(tmp_ctx,
1815                                                     winreg_pipe,
1816                                                     &key_hnd,
1817                                                     "StartTime",
1818                                                     info2->starttime);
1819                 if (!W_ERROR_IS_OK(result)) {
1820                         goto done;
1821                 }
1822         }
1823
1824         if (info2_mask & SPOOLSS_PRINTER_INFO_STATUS) {
1825                 result = winreg_printer_write_dword(tmp_ctx,
1826                                                     winreg_pipe,
1827                                                     &key_hnd,
1828                                                     "Status",
1829                                                     info2->status);
1830                 if (!W_ERROR_IS_OK(result)) {
1831                         goto done;
1832                 }
1833         }
1834
1835         if (info2_mask & SPOOLSS_PRINTER_INFO_UNTILTIME) {
1836                 result = winreg_printer_write_dword(tmp_ctx,
1837                                                     winreg_pipe,
1838                                                     &key_hnd,
1839                                                     "UntilTime",
1840                                                     info2->untiltime);
1841                 if (!W_ERROR_IS_OK(result)) {
1842                         goto done;
1843                 }
1844         }
1845
1846         result = winreg_printer_write_dword(tmp_ctx,
1847                                             winreg_pipe,
1848                                             &key_hnd,
1849                                             "ChangeID",
1850                                             winreg_printer_rev_changeid());
1851         if (!W_ERROR_IS_OK(result)) {
1852                 goto done;
1853         }
1854
1855         result = WERR_OK;
1856 done:
1857         if (winreg_pipe != NULL) {
1858                 if (is_valid_policy_hnd(&key_hnd)) {
1859                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1860                 }
1861                 if (is_valid_policy_hnd(&hive_hnd)) {
1862                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1863                 }
1864         }
1865
1866         TALLOC_FREE(tmp_ctx);
1867         return result;
1868 }
1869
1870 WERROR winreg_get_printer(TALLOC_CTX *mem_ctx,
1871                           struct auth_serversupplied_info *server_info,
1872                           const char *servername,
1873                           const char *printer,
1874                           struct spoolss_PrinterInfo2 **pinfo2)
1875 {
1876         struct spoolss_PrinterInfo2 *info2;
1877         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1878         struct rpc_pipe_client *winreg_pipe = NULL;
1879         struct policy_handle hive_hnd, key_hnd;
1880         struct spoolss_PrinterEnumValues *enum_values = NULL;
1881         struct spoolss_PrinterEnumValues *v;
1882         enum ndr_err_code ndr_err;
1883         DATA_BLOB blob;
1884         uint32_t num_values = 0;
1885         uint32_t i;
1886         char *path;
1887         WERROR result = WERR_OK;
1888         TALLOC_CTX *tmp_ctx;
1889
1890         tmp_ctx = talloc_new(mem_ctx);
1891         if (tmp_ctx == NULL) {
1892                 return WERR_NOMEM;
1893         }
1894
1895         path = winreg_printer_data_keyname(tmp_ctx, printer);
1896         if (path == NULL) {
1897                 TALLOC_FREE(tmp_ctx);
1898                 return WERR_NOMEM;
1899         }
1900
1901         result = winreg_printer_openkey(tmp_ctx,
1902                                         server_info,
1903                                         &winreg_pipe,
1904                                         path,
1905                                         "",
1906                                         false,
1907                                         access_mask,
1908                                         &hive_hnd,
1909                                         &key_hnd);
1910         if (!W_ERROR_IS_OK(result)) {
1911                 DEBUG(0, ("winreg_get_printer: Could not open key %s: %s\n",
1912                           path, win_errstr(result)));
1913                 goto done;
1914         }
1915
1916         result = winreg_printer_enumvalues(tmp_ctx,
1917                                            winreg_pipe,
1918                                            &key_hnd,
1919                                            &num_values,
1920                                            &enum_values);
1921         if (!W_ERROR_IS_OK(result)) {
1922                 DEBUG(0, ("winreg_get_printer: Could not enumerate values in %s: %s\n",
1923                           path, win_errstr(result)));
1924                 goto done;
1925         }
1926
1927         info2 = talloc_zero(tmp_ctx, struct spoolss_PrinterInfo2);
1928         if (info2 == NULL) {
1929                 result = WERR_NOMEM;
1930                 goto done;
1931         }
1932
1933         info2->servername     = EMPTY_STRING;
1934         info2->printername    = EMPTY_STRING;
1935         info2->sharename      = EMPTY_STRING;
1936         info2->portname       = EMPTY_STRING;
1937         info2->drivername     = EMPTY_STRING;
1938         info2->comment        = EMPTY_STRING;
1939         info2->location       = EMPTY_STRING;
1940         info2->sepfile        = EMPTY_STRING;
1941         info2->printprocessor = EMPTY_STRING;
1942         info2->datatype       = EMPTY_STRING;
1943         info2->parameters     = EMPTY_STRING;
1944
1945         if (servername != NULL && servername[0] != '\0') {
1946                 info2->servername = talloc_asprintf(info2, "\\\\%s", servername);
1947                 if (info2->servername == NULL) {
1948                         result = WERR_NOMEM;
1949                         goto done;
1950                 }
1951         }
1952
1953         for (i = 0; i < num_values; i++) {
1954                 v = &enum_values[i];
1955
1956                 result = winreg_enumval_to_sz(info2,
1957                                               v,
1958                                               "Name",
1959                                               &info2->printername);
1960                 if (W_ERROR_IS_OK(result) && info2->servername[0] != '\0') {
1961                         char *p = talloc_asprintf(info2, "%s\\%s",
1962                                                   info2->servername,
1963                                                   info2->printername);
1964                         if (p == NULL) {
1965                                 result = WERR_NOMEM;
1966                         }
1967                         info2->printername = p;
1968                 }
1969                 CHECK_ERROR(result);
1970
1971                 result = winreg_enumval_to_sz(info2,
1972                                               v,
1973                                               "Share Name",
1974                                               &info2->sharename);
1975                 CHECK_ERROR(result);
1976
1977                 result = winreg_enumval_to_sz(info2,
1978                                               v,
1979                                               "Port",
1980                                               &info2->portname);
1981                 CHECK_ERROR(result);
1982
1983                 result = winreg_enumval_to_sz(info2,
1984                                               v,
1985                                               "Description",
1986                                               &info2->comment);
1987                 CHECK_ERROR(result);
1988
1989                 result = winreg_enumval_to_sz(info2,
1990                                               v,
1991                                               "Location",
1992                                               &info2->location);
1993                 CHECK_ERROR(result);
1994
1995                 result = winreg_enumval_to_sz(info2,
1996                                               v,
1997                                               "Separator File",
1998                                               &info2->sepfile);
1999                 CHECK_ERROR(result);
2000
2001                 result = winreg_enumval_to_sz(info2,
2002                                               v,
2003                                               "Print Processor",
2004                                               &info2->printprocessor);
2005                 CHECK_ERROR(result);
2006
2007                 result = winreg_enumval_to_sz(info2,
2008                                               v,
2009                                               "Datatype",
2010                                               &info2->datatype);
2011                 CHECK_ERROR(result);
2012
2013                 result = winreg_enumval_to_sz(info2,
2014                                               v,
2015                                               "Parameters",
2016                                               &info2->parameters);
2017                 CHECK_ERROR(result);
2018
2019                 result = winreg_enumval_to_sz(info2,
2020                                               v,
2021                                               "Printer Driver",
2022                                               &info2->drivername);
2023                 CHECK_ERROR(result);
2024
2025                 result = winreg_enumval_to_dword(info2,
2026                                                  v,
2027                                                  "Attributes",
2028                                                  &info2->attributes);
2029                 CHECK_ERROR(result);
2030
2031                 result = winreg_enumval_to_dword(info2,
2032                                                  v,
2033                                                  "Priority",
2034                                                  &info2->priority);
2035                 CHECK_ERROR(result);
2036
2037                 result = winreg_enumval_to_dword(info2,
2038                                                  v,
2039                                                  "Default Priority",
2040                                                  &info2->defaultpriority);
2041                 CHECK_ERROR(result);
2042
2043                 result = winreg_enumval_to_dword(info2,
2044                                                  v,
2045                                                  "StartTime",
2046                                                  &info2->starttime);
2047                 CHECK_ERROR(result);
2048
2049                 result = winreg_enumval_to_dword(info2,
2050                                                  v,
2051                                                  "UntilTime",
2052                                                  &info2->untiltime);
2053                 CHECK_ERROR(result);
2054
2055                 result = winreg_enumval_to_dword(info2,
2056                                                  v,
2057                                                  "Status",
2058                                                  &info2->status);
2059                 CHECK_ERROR(result);
2060
2061                 result = winreg_enumval_to_dword(info2,
2062                                                  v,
2063                                                  "StartTime",
2064                                                  &info2->starttime);
2065                 CHECK_ERROR(result);
2066
2067                 result = winreg_enumval_to_blob(info2,
2068                                                 v,
2069                                                 "Default DevMode",
2070                                                 &blob);
2071                 if (W_ERROR_IS_OK(result)) {
2072                         info2->devmode = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2073                         if (info2->devmode == NULL) {
2074                                 result = WERR_NOMEM;
2075                                 goto done;
2076                         }
2077                         ndr_err = ndr_pull_struct_blob(&blob,
2078                                                        info2,
2079                                                        NULL,
2080                                                        info2->devmode,
2081                                                        (ndr_pull_flags_fn_t) ndr_pull_spoolss_DeviceMode);
2082                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2083                                 DEBUG(0, ("winreg_get_printer: Failed to unmarshall device mode\n"));
2084                                 result = WERR_NOMEM;
2085                                 goto done;
2086                         }
2087                 }
2088                 CHECK_ERROR(result);
2089         }
2090
2091         if (!W_ERROR_IS_OK(result)) {
2092                 DEBUG(0, ("winreg_get_printer: winreg_enumval_to_TYPE() failed "
2093                                         "for %s: %s\n",
2094                                         v->value_name,
2095                                         win_errstr(result)));
2096                 goto done;
2097         }
2098
2099         result = winreg_get_printer_secdesc(info2,
2100                                             server_info,
2101                                             printer,
2102                                             &info2->secdesc);
2103         if (!W_ERROR_IS_OK(result)) {
2104                 goto done;
2105         }
2106
2107         if (pinfo2) {
2108                 *pinfo2 = talloc_move(mem_ctx, &info2);
2109         }
2110
2111         result = WERR_OK;
2112 done:
2113         if (winreg_pipe != NULL) {
2114                 if (is_valid_policy_hnd(&key_hnd)) {
2115                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2116                 }
2117                 if (is_valid_policy_hnd(&hive_hnd)) {
2118                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2119                 }
2120         }
2121
2122         TALLOC_FREE(tmp_ctx);
2123         return result;
2124 }
2125
2126 WERROR winreg_get_printer_secdesc(TALLOC_CTX *mem_ctx,
2127                                   struct auth_serversupplied_info *server_info,
2128                                   const char *sharename,
2129                                   struct spoolss_security_descriptor **psecdesc)
2130 {
2131         struct spoolss_security_descriptor *secdesc;
2132         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2133         struct rpc_pipe_client *winreg_pipe = NULL;
2134         struct policy_handle hive_hnd, key_hnd;
2135         enum ndr_err_code ndr_err;
2136         const char *path;
2137         DATA_BLOB blob;
2138         TALLOC_CTX *tmp_ctx;
2139         WERROR result;
2140
2141         tmp_ctx = talloc_new(mem_ctx);
2142         if (tmp_ctx == NULL) {
2143                 return WERR_NOMEM;
2144         }
2145
2146         path = winreg_printer_data_keyname(tmp_ctx, sharename);
2147         if (path == NULL) {
2148                 talloc_free(tmp_ctx);
2149                 return WERR_NOMEM;
2150         }
2151
2152         ZERO_STRUCT(hive_hnd);
2153         ZERO_STRUCT(key_hnd);
2154
2155         result = winreg_printer_openkey(tmp_ctx,
2156                                         server_info,
2157                                         &winreg_pipe,
2158                                         path,
2159                                         "",
2160                                         false,
2161                                         access_mask,
2162                                         &hive_hnd,
2163                                         &key_hnd);
2164         if (!W_ERROR_IS_OK(result)) {
2165                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2166                         goto create_default;
2167                 }
2168                 goto done;
2169         }
2170
2171         result = winreg_printer_query_binary(tmp_ctx,
2172                                              winreg_pipe,
2173                                              &key_hnd,
2174                                              "Security",
2175                                              &blob);
2176         if (!W_ERROR_IS_OK(result)) {
2177                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2178                         goto create_default;
2179                 }
2180                 goto done;
2181         }
2182
2183         secdesc = talloc_zero(tmp_ctx, struct spoolss_security_descriptor);
2184         if (secdesc == NULL) {
2185                 result = WERR_NOMEM;
2186                 goto done;
2187         }
2188         ndr_err = ndr_pull_struct_blob(&blob,
2189                                        secdesc,
2190                                        NULL,
2191                                        secdesc,
2192                                        (ndr_pull_flags_fn_t) ndr_pull_security_descriptor);
2193         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2194                 DEBUG(0, ("winreg_get_secdesc: Failed to unmarshall security descriptor\n"));
2195                 result = WERR_NOMEM;
2196                 goto done;
2197         }
2198
2199         if (psecdesc) {
2200                 *psecdesc = talloc_move(mem_ctx, &secdesc);
2201         }
2202
2203         result = WERR_OK;
2204         goto done;
2205
2206 create_default:
2207         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
2208         if (!W_ERROR_IS_OK(result)) {
2209                 return result;
2210         }
2211
2212         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
2213            this security descriptor has been created when winbindd was
2214            down.  Take ownership of security descriptor. */
2215         if (sid_equal(secdesc->owner_sid, &global_sid_World)) {
2216                 DOM_SID owner_sid;
2217
2218                 /* Change sd owner to workgroup administrator */
2219
2220                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
2221                         struct spoolss_security_descriptor *new_secdesc;
2222                         size_t size;
2223
2224                         /* Create new sd */
2225                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2226
2227                         new_secdesc = make_sec_desc(tmp_ctx,
2228                                                     secdesc->revision,
2229                                                     secdesc->type,
2230                                                     &owner_sid,
2231                                                     secdesc->group_sid,
2232                                                     secdesc->sacl,
2233                                                     secdesc->dacl,
2234                                                     &size);
2235
2236                         if (new_secdesc == NULL) {
2237                                 result = WERR_NOMEM;
2238                                 goto done;
2239                         }
2240
2241                         /* Swap with other one */
2242                         secdesc = new_secdesc;
2243                 }
2244         }
2245
2246         ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL, secdesc,
2247                         (ndr_push_flags_fn_t) ndr_push_security_descriptor);
2248         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2249                 DEBUG(0, ("winreg_set_secdesc: Failed to marshall security descriptor\n"));
2250                 result = WERR_NOMEM;
2251                 goto done;
2252         }
2253
2254         result = winreg_printer_write_binary(tmp_ctx,
2255                                              winreg_pipe,
2256                                              &key_hnd,
2257                                              "Security",
2258                                              blob);
2259         if (!W_ERROR_IS_OK(result)) {
2260                 return result;
2261         }
2262
2263         if (psecdesc) {
2264                 *psecdesc = talloc_move(mem_ctx, &secdesc);
2265         }
2266
2267         result = WERR_OK;
2268 done:
2269         if (winreg_pipe != NULL) {
2270                 if (is_valid_policy_hnd(&key_hnd)) {
2271                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2272                 }
2273                 if (is_valid_policy_hnd(&hive_hnd)) {
2274                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2275                 }
2276         }
2277
2278         talloc_free(tmp_ctx);
2279         return result;
2280 }
2281
2282 WERROR winreg_set_printer_secdesc(TALLOC_CTX *mem_ctx,
2283                                   struct auth_serversupplied_info *server_info,
2284                                   const char *sharename,
2285                                   const struct spoolss_security_descriptor *secdesc)
2286 {
2287         const struct spoolss_security_descriptor *new_secdesc = secdesc;
2288         struct spoolss_security_descriptor *old_secdesc;
2289         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2290         struct rpc_pipe_client *winreg_pipe = NULL;
2291         struct policy_handle hive_hnd, key_hnd;
2292         enum ndr_err_code ndr_err;
2293         const char *path;
2294         DATA_BLOB blob;
2295         TALLOC_CTX *tmp_ctx;
2296         WERROR result;
2297
2298         tmp_ctx = talloc_new(mem_ctx);
2299         if (tmp_ctx == NULL) {
2300                 return WERR_NOMEM;
2301         }
2302
2303         path = winreg_printer_data_keyname(tmp_ctx, sharename);
2304         if (path == NULL) {
2305                 talloc_free(tmp_ctx);
2306                 return WERR_NOMEM;
2307         }
2308
2309         /*
2310          * The old owner and group sids of the security descriptor are not
2311          * present when new ACEs are added or removed by changing printer
2312          * permissions through NT.  If they are NULL in the new security
2313          * descriptor then copy them over from the old one.
2314          */
2315         if (!secdesc->owner_sid || !secdesc->group_sid) {
2316                 DOM_SID *owner_sid, *group_sid;
2317                 SEC_ACL *dacl, *sacl;
2318                 size_t size;
2319
2320                 result = winreg_get_printer_secdesc(tmp_ctx,
2321                                                     server_info,
2322                                                     sharename,
2323                                                     &old_secdesc);
2324                 if (!W_ERROR_IS_OK(result)) {
2325                         talloc_free(tmp_ctx);
2326                         return result;
2327                 }
2328
2329                 /* Pick out correct owner and group sids */
2330                 owner_sid = secdesc->owner_sid ?
2331                             secdesc->owner_sid :
2332                             old_secdesc->owner_sid;
2333
2334                 group_sid = secdesc->group_sid ?
2335                             secdesc->group_sid :
2336                             old_secdesc->group_sid;
2337
2338                 dacl = secdesc->dacl ?
2339                        secdesc->dacl :
2340                        old_secdesc->dacl;
2341
2342                 sacl = secdesc->sacl ?
2343                        secdesc->sacl :
2344                        old_secdesc->sacl;
2345
2346                 /* Make a deep copy of the security descriptor */
2347                 new_secdesc = make_sec_desc(tmp_ctx,
2348                                             secdesc->revision,
2349                                             secdesc->type,
2350                                             owner_sid,
2351                                             group_sid,
2352                                             sacl,
2353                                             dacl,
2354                                             &size);
2355                 if (new_secdesc == NULL) {
2356                         talloc_free(tmp_ctx);
2357                         return WERR_NOMEM;
2358                 }
2359         }
2360
2361         ZERO_STRUCT(hive_hnd);
2362         ZERO_STRUCT(key_hnd);
2363
2364         result = winreg_printer_openkey(tmp_ctx,
2365                                         server_info,
2366                                         &winreg_pipe,
2367                                         path,
2368                                         "",
2369                                         false,
2370                                         access_mask,
2371                                         &hive_hnd,
2372                                         &key_hnd);
2373         if (!W_ERROR_IS_OK(result)) {
2374                 goto done;
2375         }
2376
2377         ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL, new_secdesc,
2378                         (ndr_push_flags_fn_t) ndr_push_security_descriptor);
2379         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2380                 DEBUG(0, ("winreg_set_secdesc: Failed to marshall security descriptor\n"));
2381                 result = WERR_NOMEM;
2382                 goto done;
2383         }
2384
2385         result = winreg_printer_write_binary(tmp_ctx,
2386                                              winreg_pipe,
2387                                              &key_hnd,
2388                                              "Security",
2389                                              blob);
2390
2391 done:
2392         if (winreg_pipe != NULL) {
2393                 if (is_valid_policy_hnd(&key_hnd)) {
2394                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2395                 }
2396                 if (is_valid_policy_hnd(&hive_hnd)) {
2397                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2398                 }
2399         }
2400
2401         talloc_free(tmp_ctx);
2402         return result;
2403 }
2404
2405 /* Set printer data over the winreg pipe. */
2406 WERROR winreg_set_printer_dataex(TALLOC_CTX *mem_ctx,
2407                                  struct auth_serversupplied_info *server_info,
2408                                  const char *printer,
2409                                  const char *key,
2410                                  const char *value,
2411                                  enum winreg_Type type,
2412                                  uint8_t *data,
2413                                  uint32_t data_size)
2414 {
2415         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2416         struct rpc_pipe_client *winreg_pipe = NULL;
2417         struct policy_handle hive_hnd, key_hnd;
2418         struct winreg_String wvalue;
2419         char *path;
2420         WERROR result = WERR_OK;
2421         NTSTATUS status;
2422         TALLOC_CTX *tmp_ctx;
2423
2424         tmp_ctx = talloc_new(mem_ctx);
2425         if (tmp_ctx == NULL) {
2426                 return WERR_NOMEM;
2427         }
2428
2429         path = winreg_printer_data_keyname(tmp_ctx, printer);
2430         if (path == NULL) {
2431                 TALLOC_FREE(tmp_ctx);
2432                 return WERR_NOMEM;
2433         }
2434
2435         ZERO_STRUCT(hive_hnd);
2436         ZERO_STRUCT(key_hnd);
2437
2438         DEBUG(8, ("winreg_set_printer_dataex: Open printer key %s, value %s, access_mask: 0x%05x for [%s]\n",
2439                         key, value, access_mask, printer));
2440         result = winreg_printer_openkey(tmp_ctx,
2441                                         server_info,
2442                                         &winreg_pipe,
2443                                         path,
2444                                         key,
2445                                         true,
2446                                         access_mask,
2447                                         &hive_hnd,
2448                                         &key_hnd);
2449         if (!W_ERROR_IS_OK(result)) {
2450                 DEBUG(0, ("winreg_set_printer_dataex: Could not open key %s: %s\n",
2451                           key, win_errstr(result)));
2452                 goto done;
2453         }
2454
2455         wvalue.name = value;
2456         status = rpccli_winreg_SetValue(winreg_pipe,
2457                                         tmp_ctx,
2458                                         &key_hnd,
2459                                         wvalue,
2460                                         type,
2461                                         data,
2462                                         data_size,
2463                                         &result);
2464         if (!NT_STATUS_IS_OK(status)) {
2465                 DEBUG(0, ("winreg_set_printer_dataex: Could not set value %s: %s\n",
2466                           value, nt_errstr(status)));
2467                 if (!W_ERROR_IS_OK(result)) {
2468                         goto done;
2469                 }
2470                 result = ntstatus_to_werror(status);
2471                 goto done;
2472         }
2473
2474         result = WERR_OK;
2475 done:
2476         if (winreg_pipe != NULL) {
2477                 if (is_valid_policy_hnd(&key_hnd)) {
2478                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2479                 }
2480                 if (is_valid_policy_hnd(&hive_hnd)) {
2481                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2482                 }
2483         }
2484
2485         TALLOC_FREE(tmp_ctx);
2486         return result;
2487 }
2488
2489 /* Get printer data over a winreg pipe. */
2490 WERROR winreg_get_printer_dataex(TALLOC_CTX *mem_ctx,
2491                                  struct auth_serversupplied_info *server_info,
2492                                  const char *printer,
2493                                  const char *key,
2494                                  const char *value,
2495                                  enum winreg_Type *type,
2496                                  uint8_t **data,
2497                                  uint32_t *data_size)
2498 {
2499         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2500         struct rpc_pipe_client *winreg_pipe = NULL;
2501         struct policy_handle hive_hnd, key_hnd;
2502         struct winreg_String wvalue;
2503         enum winreg_Type type_in;
2504         char *path;
2505         uint8_t *data_in;
2506         uint32_t data_in_size = 0;
2507         uint32_t value_len = 0;
2508         WERROR result = WERR_OK;
2509         NTSTATUS status;
2510         TALLOC_CTX *tmp_ctx;
2511
2512         tmp_ctx = talloc_new(mem_ctx);
2513         if (tmp_ctx == NULL) {
2514                 return WERR_NOMEM;
2515         }
2516
2517         path = winreg_printer_data_keyname(tmp_ctx, printer);
2518         if (path == NULL) {
2519                 TALLOC_FREE(tmp_ctx);
2520                 return WERR_NOMEM;
2521         }
2522
2523         ZERO_STRUCT(hive_hnd);
2524         ZERO_STRUCT(key_hnd);
2525
2526         result = winreg_printer_openkey(tmp_ctx,
2527                                         server_info,
2528                                         &winreg_pipe,
2529                                         path,
2530                                         key,
2531                                         false,
2532                                         access_mask,
2533                                         &hive_hnd,
2534                                         &key_hnd);
2535         if (!W_ERROR_IS_OK(result)) {
2536                 DEBUG(0, ("winreg_get_printer_dataex: Could not open key %s: %s\n",
2537                           key, win_errstr(result)));
2538                 goto done;
2539         }
2540
2541         wvalue.name = value;
2542
2543         /*
2544          * call QueryValue once with data == NULL to get the
2545          * needed memory size to be allocated, then allocate
2546          * data buffer and call again.
2547          */
2548         status = rpccli_winreg_QueryValue(winreg_pipe,
2549                                           tmp_ctx,
2550                                           &key_hnd,
2551                                           &wvalue,
2552                                           &type_in,
2553                                           NULL,
2554                                           &data_in_size,
2555                                           &value_len,
2556                                           &result);
2557         if (!NT_STATUS_IS_OK(status)) {
2558                 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2559                           value, nt_errstr(status)));
2560                 if (!W_ERROR_IS_OK(result)) {
2561                         goto done;
2562                 }
2563                 result = ntstatus_to_werror(status);
2564                 goto done;
2565         }
2566
2567         data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
2568         if (data_in == NULL) {
2569                 result = WERR_NOMEM;
2570                 goto done;
2571         }
2572         value_len = 0;
2573
2574         status = rpccli_winreg_QueryValue(winreg_pipe,
2575                                           tmp_ctx,
2576                                           &key_hnd,
2577                                           &wvalue,
2578                                           &type_in,
2579                                           data_in,
2580                                           &data_in_size,
2581                                           &value_len,
2582                                           &result);
2583         if (!NT_STATUS_IS_OK(status)) {
2584                 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2585                           value, nt_errstr(status)));
2586                 if (!W_ERROR_IS_OK(result)) {
2587                         result = ntstatus_to_werror(status);
2588                 }
2589                 goto done;
2590         }
2591
2592         *type = type_in;
2593         *data_size = data_in_size;
2594         if (data_in_size) {
2595                 *data = talloc_move(mem_ctx, &data_in);
2596         }
2597
2598         result = WERR_OK;
2599 done:
2600         if (winreg_pipe != NULL) {
2601                 if (is_valid_policy_hnd(&key_hnd)) {
2602                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2603                 }
2604                 if (is_valid_policy_hnd(&hive_hnd)) {
2605                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2606                 }
2607         }
2608
2609         TALLOC_FREE(tmp_ctx);
2610         return result;
2611 }
2612
2613 /* Enumerate on the values of a given key and provide the data. */
2614 WERROR winreg_enum_printer_dataex(TALLOC_CTX *mem_ctx,
2615                                   struct auth_serversupplied_info *server_info,
2616                                   const char *printer,
2617                                   const char *key,
2618                                   uint32_t *pnum_values,
2619                                   struct spoolss_PrinterEnumValues **penum_values)
2620 {
2621         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2622         struct rpc_pipe_client *winreg_pipe = NULL;
2623         struct policy_handle hive_hnd, key_hnd;
2624
2625         struct spoolss_PrinterEnumValues *enum_values = NULL;
2626         uint32_t num_values = 0;
2627         char *path;
2628         WERROR result = WERR_OK;
2629
2630         TALLOC_CTX *tmp_ctx;
2631
2632         tmp_ctx = talloc_new(mem_ctx);
2633         if (tmp_ctx == NULL) {
2634                 return WERR_NOMEM;
2635         }
2636
2637         path = winreg_printer_data_keyname(tmp_ctx, printer);
2638         if (path == NULL) {
2639                 TALLOC_FREE(tmp_ctx);
2640                 return WERR_NOMEM;
2641         }
2642
2643         result = winreg_printer_openkey(tmp_ctx,
2644                                         server_info,
2645                                         &winreg_pipe,
2646                                         path,
2647                                         key,
2648                                         false,
2649                                         access_mask,
2650                                         &hive_hnd,
2651                                         &key_hnd);
2652         if (!W_ERROR_IS_OK(result)) {
2653                 DEBUG(0, ("winreg_enum_printer_dataex: Could not open key %s: %s\n",
2654                           key, win_errstr(result)));
2655                 goto done;
2656         }
2657
2658         result = winreg_printer_enumvalues(tmp_ctx,
2659                                            winreg_pipe,
2660                                            &key_hnd,
2661                                            &num_values,
2662                                            &enum_values);
2663         if (!W_ERROR_IS_OK(result)) {
2664                 DEBUG(0, ("winreg_enum_printer_dataex: Could not enumerate values in %s: %s\n",
2665                           key, win_errstr(result)));
2666                 goto done;
2667         }
2668
2669         *pnum_values = num_values;
2670         if (penum_values) {
2671                 *penum_values = talloc_move(mem_ctx, &enum_values);
2672         }
2673
2674         result = WERR_OK;
2675 done:
2676         if (winreg_pipe != NULL) {
2677                 if (is_valid_policy_hnd(&key_hnd)) {
2678                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2679                 }
2680                 if (is_valid_policy_hnd(&hive_hnd)) {
2681                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2682                 }
2683         }
2684
2685         TALLOC_FREE(tmp_ctx);
2686         return result;
2687 }
2688
2689 /* Delete printer data over a winreg pipe. */
2690 WERROR winreg_delete_printer_dataex(TALLOC_CTX *mem_ctx,
2691                                     struct auth_serversupplied_info *server_info,
2692                                     const char *printer,
2693                                     const char *key,
2694                                     const char *value)
2695 {
2696         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2697         struct rpc_pipe_client *winreg_pipe = NULL;
2698         struct policy_handle hive_hnd, key_hnd;
2699         struct winreg_String wvalue;
2700         char *path;
2701         WERROR result = WERR_OK;
2702         NTSTATUS status;
2703
2704         TALLOC_CTX *tmp_ctx;
2705
2706         tmp_ctx = talloc_new(mem_ctx);
2707         if (tmp_ctx == NULL) {
2708                 return WERR_NOMEM;
2709         }
2710
2711         path = winreg_printer_data_keyname(tmp_ctx, printer);
2712         if (path == NULL) {
2713                 TALLOC_FREE(tmp_ctx);
2714                 return WERR_NOMEM;
2715         }
2716
2717         ZERO_STRUCT(hive_hnd);
2718         ZERO_STRUCT(key_hnd);
2719
2720         result = winreg_printer_openkey(tmp_ctx,
2721                                         server_info,
2722                                         &winreg_pipe,
2723                                         path,
2724                                         key,
2725                                         false,
2726                                         access_mask,
2727                                         &hive_hnd,
2728                                         &key_hnd);
2729         if (!W_ERROR_IS_OK(result)) {
2730                 DEBUG(0, ("winreg_delete_printer_dataex: Could not open key %s: %s\n",
2731                           key, win_errstr(result)));
2732                 goto done;
2733         }
2734
2735         wvalue.name = value;
2736         status = rpccli_winreg_DeleteValue(winreg_pipe,
2737                                            tmp_ctx,
2738                                            &key_hnd,
2739                                            wvalue,
2740                                            &result);
2741         if (!NT_STATUS_IS_OK(status)) {
2742                 DEBUG(0, ("winreg_delete_printer_dataex: Could not delete value %s: %s\n",
2743                           value, nt_errstr(status)));
2744                 if (!W_ERROR_IS_OK(result)) {
2745                         goto done;
2746                 }
2747                 result = ntstatus_to_werror(status);
2748                 goto done;
2749         }
2750
2751         result = WERR_OK;
2752 done:
2753         if (winreg_pipe != NULL) {
2754                 if (is_valid_policy_hnd(&key_hnd)) {
2755                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2756                 }
2757                 if (is_valid_policy_hnd(&hive_hnd)) {
2758                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2759                 }
2760         }
2761
2762         TALLOC_FREE(tmp_ctx);
2763         return result;
2764 }
2765
2766 /* Enumerate on the subkeys of a given key and provide the data. */
2767 WERROR winreg_enum_printer_key(TALLOC_CTX *mem_ctx,
2768                                struct auth_serversupplied_info *server_info,
2769                                const char *printer,
2770                                const char *key,
2771                                uint32_t *pnum_subkeys,
2772                                const char ***psubkeys)
2773 {
2774         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2775         struct rpc_pipe_client *winreg_pipe = NULL;
2776         struct policy_handle hive_hnd, key_hnd;
2777         char *path;
2778         const char **subkeys = NULL;
2779         uint32_t num_subkeys = -1;
2780
2781         WERROR result = WERR_OK;
2782
2783         TALLOC_CTX *tmp_ctx;
2784
2785         tmp_ctx = talloc_new(mem_ctx);
2786         if (tmp_ctx == NULL) {
2787                 return WERR_NOMEM;
2788         }
2789
2790         path = winreg_printer_data_keyname(tmp_ctx, printer);
2791         if (path == NULL) {
2792                 TALLOC_FREE(tmp_ctx);
2793                 return WERR_NOMEM;
2794         }
2795
2796         ZERO_STRUCT(hive_hnd);
2797         ZERO_STRUCT(key_hnd);
2798
2799         result = winreg_printer_openkey(tmp_ctx,
2800                                         server_info,
2801                                         &winreg_pipe,
2802                                         path,
2803                                         key,
2804                                         false,
2805                                         access_mask,
2806                                         &hive_hnd,
2807                                         &key_hnd);
2808         if (!W_ERROR_IS_OK(result)) {
2809                 DEBUG(0, ("winreg_enum_printer_key: Could not open key %s: %s\n",
2810                           key, win_errstr(result)));
2811                 goto done;
2812         }
2813
2814         result = winreg_printer_enumkeys(tmp_ctx,
2815                                          winreg_pipe,
2816                                          &key_hnd,
2817                                          &num_subkeys,
2818                                          &subkeys);
2819         if (!W_ERROR_IS_OK(result)) {
2820                 DEBUG(0, ("winreg_enum_printer_key: Could not enumerate subkeys in %s: %s\n",
2821                           key, win_errstr(result)));
2822                 goto done;
2823         }
2824
2825         *pnum_subkeys = num_subkeys;
2826         if (psubkeys) {
2827                 *psubkeys = talloc_move(mem_ctx, &subkeys);
2828         }
2829
2830         result = WERR_OK;
2831 done:
2832         if (winreg_pipe != NULL) {
2833                 if (is_valid_policy_hnd(&key_hnd)) {
2834                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2835                 }
2836                 if (is_valid_policy_hnd(&hive_hnd)) {
2837                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2838                 }
2839         }
2840
2841         TALLOC_FREE(tmp_ctx);
2842         return result;
2843 }
2844
2845 /* Delete a key with subkeys of a given printer. */
2846 WERROR winreg_delete_printer_key(TALLOC_CTX *mem_ctx,
2847                                  struct auth_serversupplied_info *server_info,
2848                                  const char *printer,
2849                                  const char *key)
2850 {
2851         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2852         struct rpc_pipe_client *winreg_pipe = NULL;
2853         struct policy_handle hive_hnd, key_hnd;
2854         char *keyname;
2855         char *path;
2856         WERROR result;
2857         TALLOC_CTX *tmp_ctx;
2858
2859         tmp_ctx = talloc_new(mem_ctx);
2860         if (tmp_ctx == NULL) {
2861                 return WERR_NOMEM;
2862         }
2863
2864         path = winreg_printer_data_keyname(tmp_ctx, printer);
2865         if (path == NULL) {
2866                 TALLOC_FREE(tmp_ctx);
2867                 return WERR_NOMEM;
2868         }
2869
2870         result = winreg_printer_openkey(tmp_ctx,
2871                                         server_info,
2872                                         &winreg_pipe,
2873                                         path,
2874                                         key,
2875                                         false,
2876                                         access_mask,
2877                                         &hive_hnd,
2878                                         &key_hnd);
2879         if (!W_ERROR_IS_OK(result)) {
2880                 /* key doesn't exist */
2881                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2882                         result = WERR_OK;
2883                         goto done;
2884                 }
2885
2886                 DEBUG(0, ("winreg_delete_printer_key: Could not open key %s: %s\n",
2887                           key, win_errstr(result)));
2888                 goto done;
2889         }
2890
2891         if (is_valid_policy_hnd(&key_hnd)) {
2892                 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2893         }
2894
2895         if (key == NULL || key[0] == '\0') {
2896                 keyname = path;
2897         } else {
2898                 keyname = talloc_asprintf(tmp_ctx,
2899                                           "%s\\%s",
2900                                           path,
2901                                           key);
2902                 if (keyname == NULL) {
2903                         result = WERR_NOMEM;
2904                         goto done;
2905                 }
2906         }
2907
2908         result = winreg_printer_delete_subkeys(tmp_ctx,
2909                                                winreg_pipe,
2910                                                &hive_hnd,
2911                                                access_mask,
2912                                                keyname);
2913         if (!W_ERROR_IS_OK(result)) {
2914                 DEBUG(0, ("winreg_delete_printer_key: Could not delete key %s: %s\n",
2915                           key, win_errstr(result)));
2916                 goto done;
2917         }
2918
2919 done:
2920         if (winreg_pipe != NULL) {
2921                 if (is_valid_policy_hnd(&key_hnd)) {
2922                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2923                 }
2924                 if (is_valid_policy_hnd(&hive_hnd)) {
2925                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2926                 }
2927         }
2928
2929         TALLOC_FREE(tmp_ctx);
2930         return result;
2931 }
2932
2933 WERROR winreg_printer_update_changeid(TALLOC_CTX *mem_ctx,
2934                                       struct auth_serversupplied_info *server_info,
2935                                       const char *printer)
2936 {
2937         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2938         struct rpc_pipe_client *winreg_pipe = NULL;
2939         struct policy_handle hive_hnd, key_hnd;
2940         char *path;
2941         WERROR result;
2942         TALLOC_CTX *tmp_ctx;
2943
2944         tmp_ctx = talloc_new(mem_ctx);
2945         if (tmp_ctx == NULL) {
2946                 return WERR_NOMEM;
2947         }
2948
2949         path = winreg_printer_data_keyname(tmp_ctx, printer);
2950         if (path == NULL) {
2951                 TALLOC_FREE(tmp_ctx);
2952                 return WERR_NOMEM;
2953         }
2954
2955         ZERO_STRUCT(hive_hnd);
2956         ZERO_STRUCT(key_hnd);
2957
2958         result = winreg_printer_openkey(tmp_ctx,
2959                                         server_info,
2960                                         &winreg_pipe,
2961                                         path,
2962                                         "",
2963                                         false,
2964                                         access_mask,
2965                                         &hive_hnd,
2966                                         &key_hnd);
2967         if (!W_ERROR_IS_OK(result)) {
2968                 DEBUG(0, ("winreg_printer_update_changeid: Could not open key %s: %s\n",
2969                           path, win_errstr(result)));
2970                 goto done;
2971         }
2972
2973         result = winreg_printer_write_dword(tmp_ctx,
2974                                             winreg_pipe,
2975                                             &key_hnd,
2976                                             "ChangeID",
2977                                             winreg_printer_rev_changeid());
2978         if (!W_ERROR_IS_OK(result)) {
2979                 goto done;
2980         }
2981
2982         result = WERR_OK;
2983 done:
2984         if (winreg_pipe != NULL) {
2985                 if (is_valid_policy_hnd(&key_hnd)) {
2986                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2987                 }
2988                 if (is_valid_policy_hnd(&hive_hnd)) {
2989                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2990                 }
2991         }
2992
2993         TALLOC_FREE(tmp_ctx);
2994         return result;
2995 }
2996
2997 WERROR winreg_printer_get_changeid(TALLOC_CTX *mem_ctx,
2998                                    struct auth_serversupplied_info *server_info,
2999                                    const char *printer,
3000                                    uint32_t *pchangeid)
3001 {
3002         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3003         struct rpc_pipe_client *winreg_pipe = NULL;
3004         struct policy_handle hive_hnd, key_hnd;
3005         uint32_t changeid = 0;
3006         char *path;
3007         WERROR result;
3008         TALLOC_CTX *tmp_ctx;
3009
3010         tmp_ctx = talloc_new(mem_ctx);
3011         if (tmp_ctx == NULL) {
3012                 return WERR_NOMEM;
3013         }
3014
3015         path = winreg_printer_data_keyname(tmp_ctx, printer);
3016         if (path == NULL) {
3017                 TALLOC_FREE(tmp_ctx);
3018                 return WERR_NOMEM;
3019         }
3020
3021         ZERO_STRUCT(hive_hnd);
3022         ZERO_STRUCT(key_hnd);
3023
3024         result = winreg_printer_openkey(tmp_ctx,
3025                                         server_info,
3026                                         &winreg_pipe,
3027                                         path,
3028                                         "",
3029                                         false,
3030                                         access_mask,
3031                                         &hive_hnd,
3032                                         &key_hnd);
3033         if (!W_ERROR_IS_OK(result)) {
3034                 DEBUG(0, ("winreg_printer_get_changeid: Could not open key %s: %s\n",
3035                           path, win_errstr(result)));
3036                 goto done;
3037         }
3038
3039         DEBUG(0, ("winreg_printer_get_changeid: get changeid from %s\n", path));
3040         result = winreg_printer_query_dword(tmp_ctx,
3041                                             winreg_pipe,
3042                                             &key_hnd,
3043                                             "ChangeID",
3044                                             &changeid);
3045         if (!W_ERROR_IS_OK(result)) {
3046                 goto done;
3047         }
3048
3049         if (pchangeid) {
3050                 *pchangeid = changeid;
3051         }
3052
3053         result = WERR_OK;
3054 done:
3055         if (winreg_pipe != NULL) {
3056                 if (is_valid_policy_hnd(&key_hnd)) {
3057                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3058                 }
3059                 if (is_valid_policy_hnd(&hive_hnd)) {
3060                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
3061                 }
3062         }
3063
3064         TALLOC_FREE(tmp_ctx);
3065         return result;
3066 }
3067
3068 /*
3069  * The special behaviour of the spoolss forms is documented at the website:
3070  *
3071  * Managing Win32 Printserver Forms
3072  * http://unixwiz.net/techtips/winspooler-forms.html
3073  */
3074
3075 WERROR winreg_printer_addform1(TALLOC_CTX *mem_ctx,
3076                                struct auth_serversupplied_info *server_info,
3077                                struct spoolss_AddFormInfo1 *form)
3078 {
3079         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3080         struct rpc_pipe_client *winreg_pipe = NULL;
3081         struct policy_handle hive_hnd, key_hnd;
3082         struct winreg_String wvalue;
3083         DATA_BLOB blob;
3084         uint32_t num_info = 0;
3085         union spoolss_FormInfo *info = NULL;
3086         uint32_t i;
3087         WERROR result;
3088         NTSTATUS status;
3089         TALLOC_CTX *tmp_ctx;
3090
3091         tmp_ctx = talloc_new(mem_ctx);
3092         if (tmp_ctx == NULL) {
3093                 return WERR_NOMEM;
3094         }
3095
3096         ZERO_STRUCT(hive_hnd);
3097         ZERO_STRUCT(key_hnd);
3098
3099         result = winreg_printer_openkey(tmp_ctx,
3100                                         server_info,
3101                                         &winreg_pipe,
3102                                         TOP_LEVEL_CONTROL_FORMS_KEY,
3103                                         "",
3104                                         true,
3105                                         access_mask,
3106                                         &hive_hnd,
3107                                         &key_hnd);
3108         if (!W_ERROR_IS_OK(result)) {
3109                 DEBUG(0, ("winreg_printer_addform1: Could not open key %s: %s\n",
3110                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3111                 goto done;
3112         }
3113
3114         result = winreg_printer_enumforms1(tmp_ctx, server_info, &num_info, &info);
3115         if (!W_ERROR_IS_OK(result)) {
3116                 DEBUG(0, ("winreg_printer_addform: Could not enum keys %s: %s\n",
3117                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3118                 goto done;
3119         }
3120
3121         /* If form name already exists or is builtin return ALREADY_EXISTS */
3122         for (i = 0; i < num_info; i++) {
3123                 if (strequal(info[i].info1.form_name, form->form_name)) {
3124                         result = WERR_FILE_EXISTS;
3125                         goto done;
3126                 }
3127         }
3128
3129         wvalue.name = form->form_name;
3130
3131         blob = data_blob_talloc(tmp_ctx, NULL, 32);
3132         SIVAL(blob.data,  0, form->size.width);
3133         SIVAL(blob.data,  4, form->size.height);
3134         SIVAL(blob.data,  8, form->area.left);
3135         SIVAL(blob.data, 12, form->area.top);
3136         SIVAL(blob.data, 16, form->area.right);
3137         SIVAL(blob.data, 20, form->area.bottom);
3138         SIVAL(blob.data, 24, num_info + 1); /* FIXME */
3139         SIVAL(blob.data, 28, form->flags);
3140
3141         status = rpccli_winreg_SetValue(winreg_pipe,
3142                                         tmp_ctx,
3143                                         &key_hnd,
3144                                         wvalue,
3145                                         REG_BINARY,
3146                                         blob.data,
3147                                         blob.length,
3148                                         &result);
3149         if (!NT_STATUS_IS_OK(status)) {
3150                 DEBUG(0, ("winreg_printer_addform1: Could not set value %s: %s\n",
3151                           wvalue.name, nt_errstr(status)));
3152                 if (!W_ERROR_IS_OK(result)) {
3153                         goto done;
3154                 }
3155                 result = ntstatus_to_werror(status);
3156                 goto done;
3157         }
3158
3159         result = WERR_OK;
3160 done:
3161         if (winreg_pipe != NULL) {
3162                 if (is_valid_policy_hnd(&key_hnd)) {
3163                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3164                 }
3165                 if (is_valid_policy_hnd(&hive_hnd)) {
3166                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
3167                 }
3168         }
3169
3170         TALLOC_FREE(info);
3171         TALLOC_FREE(tmp_ctx);
3172         return result;
3173 }
3174
3175 WERROR winreg_printer_enumforms1(TALLOC_CTX *mem_ctx,
3176                                  struct auth_serversupplied_info *server_info,
3177                                  uint32_t *pnum_info,
3178                                  union spoolss_FormInfo **pinfo)
3179 {
3180         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3181         struct rpc_pipe_client *winreg_pipe = NULL;
3182         struct policy_handle hive_hnd, key_hnd;
3183         union spoolss_FormInfo *info;
3184         struct spoolss_PrinterEnumValues *enum_values = NULL;
3185         uint32_t num_values = 0;
3186         uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
3187         uint32_t i;
3188         WERROR result;
3189         TALLOC_CTX *tmp_ctx;
3190
3191         tmp_ctx = talloc_new(mem_ctx);
3192         if (tmp_ctx == NULL) {
3193                 return WERR_NOMEM;
3194         }
3195
3196         ZERO_STRUCT(hive_hnd);
3197         ZERO_STRUCT(key_hnd);
3198
3199         result = winreg_printer_openkey(tmp_ctx,
3200                      &nb