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