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