5b47154f41ba82fc249e984c3fa6d8dd6cba3aa0
[nivanova/samba-autobuild/.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
30 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
31 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
32 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
33 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
34
35 #define EMPTY_STRING ""
36
37 #define FILL_STRING(mem_ctx, in, out) \
38         do { \
39                 if (in && strlen(in)) { \
40                         out = talloc_strdup(mem_ctx, in); \
41                 } else { \
42                         out = talloc_strdup(mem_ctx, ""); \
43                 } \
44                 W_ERROR_HAVE_NO_MEMORY(out); \
45         } while (0);
46
47 #define CHECK_ERROR(result) \
48         if (W_ERROR_IS_OK(result)) continue; \
49         if (W_ERROR_EQUAL(result, WERR_NOT_FOUND)) result = WERR_OK; \
50         if (!W_ERROR_IS_OK(result)) break
51
52 /*        FLAGS,                NAME,                              with,   height,   left, top, right, bottom */
53 static const struct spoolss_FormInfo1 builtin_forms1[] = {
54         { SPOOLSS_FORM_BUILTIN, "10x11",                          {0x3e030,0x44368}, {0x0,0x0,0x3e030,0x44368} },
55         { SPOOLSS_FORM_BUILTIN, "10x14",                          {0x3e030,0x56d10}, {0x0,0x0,0x3e030,0x56d10} },
56         { SPOOLSS_FORM_BUILTIN, "11x17",                          {0x44368,0x696b8}, {0x0,0x0,0x44368,0x696b8} },
57         { SPOOLSS_FORM_BUILTIN, "12x11",                          {0x4a724,0x443e1}, {0x0,0x0,0x4a724,0x443e1} },
58         { SPOOLSS_FORM_BUILTIN, "15x11",                          {0x5d048,0x44368}, {0x0,0x0,0x5d048,0x44368} },
59         { SPOOLSS_FORM_BUILTIN, "6 3/4 Envelope",                 {0x167ab,0x284ec}, {0x0,0x0,0x167ab,0x284ec} },
60         { SPOOLSS_FORM_BUILTIN, "9x11",                           {0x37cf8,0x44368}, {0x0,0x0,0x37cf8,0x44368} },
61         { SPOOLSS_FORM_BUILTIN, "A0",                             {0xcd528,0x122488},{0x0,0x0,0xcd528,0x122488} },
62         { SPOOLSS_FORM_BUILTIN, "A1",                             {0x91050,0xcd528}, {0x0,0x0,0x91050,0xcd528} },
63         { SPOOLSS_FORM_BUILTIN, "A2",                             {0x668a0,0x91050}, {0x0,0x0,0x668a0,0x91050} },
64         { SPOOLSS_FORM_BUILTIN, "A3 Extra Transverse",            {0x4e9d0,0x6ca48}, {0x0,0x0,0x4e9d0,0x6ca48} },
65         { SPOOLSS_FORM_BUILTIN, "A3 Extra",                       {0x4e9d0,0x6ca48}, {0x0,0x0,0x4e9d0,0x6ca48} },
66         { SPOOLSS_FORM_BUILTIN, "A3 Rotated",                     {0x668a0,0x48828}, {0x0,0x0,0x668a0,0x48828} },
67         { SPOOLSS_FORM_BUILTIN, "A3 Transverse",                  {0x48828,0x668a0}, {0x0,0x0,0x48828,0x668a0} },
68         { SPOOLSS_FORM_BUILTIN, "A3",                             {0x48828,0x668a0}, {0x0,0x0,0x48828,0x668a0} },
69         { SPOOLSS_FORM_BUILTIN, "A4 Extra",                       {0x397c2,0x4eb16}, {0x0,0x0,0x397c2,0x4eb16} },
70         { SPOOLSS_FORM_BUILTIN, "A4 Plus",                        {0x33450,0x50910}, {0x0,0x0,0x33450,0x50910} },
71         { SPOOLSS_FORM_BUILTIN, "A4 Rotated",                     {0x48828,0x33450}, {0x0,0x0,0x48828,0x33450} },
72         { SPOOLSS_FORM_BUILTIN, "A4 Small",                       {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
73         { SPOOLSS_FORM_BUILTIN, "A4 Transverse",                  {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
74         { SPOOLSS_FORM_BUILTIN, "A4",                             {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
75         { SPOOLSS_FORM_BUILTIN, "A5 Extra",                       {0x2a7b0,0x395f8}, {0x0,0x0,0x2a7b0,0x395f8} },
76         { SPOOLSS_FORM_BUILTIN, "A5 Rotated",                     {0x33450,0x24220}, {0x0,0x0,0x33450,0x24220} },
77         { SPOOLSS_FORM_BUILTIN, "A5 Transverse",                  {0x24220,0x33450}, {0x0,0x0,0x24220,0x33450} },
78         { SPOOLSS_FORM_BUILTIN, "A5",                             {0x24220,0x33450}, {0x0,0x0,0x24220,0x33450} },
79         { SPOOLSS_FORM_BUILTIN, "A6 Rotated",                     {0x24220,0x19a28}, {0x0,0x0,0x24220,0x19a28} },
80         { SPOOLSS_FORM_BUILTIN, "A6",                             {0x19a28,0x24220}, {0x0,0x0,0x19a28,0x24220} },
81         { SPOOLSS_FORM_BUILTIN, "B4 (ISO)",                       {0x3d090,0x562e8}, {0x0,0x0,0x3d090,0x562e8} },
82         { SPOOLSS_FORM_BUILTIN, "B4 (JIS) Rotated",               {0x58de0,0x3ebe8}, {0x0,0x0,0x58de0,0x3ebe8} },
83         { SPOOLSS_FORM_BUILTIN, "B4 (JIS)",                       {0x3ebe8,0x58de0}, {0x0,0x0,0x3ebe8,0x58de0} },
84         { SPOOLSS_FORM_BUILTIN, "B5 (ISO) Extra",                 {0x31128,0x43620}, {0x0,0x0,0x31128,0x43620} },
85         { SPOOLSS_FORM_BUILTIN, "B5 (JIS) Rotated",               {0x3ebe8,0x2c6f0}, {0x0,0x0,0x3ebe8,0x2c6f0} },
86         { SPOOLSS_FORM_BUILTIN, "B5 (JIS) Transverse",            {0x2c6f0,0x3ebe8}, {0x0,0x0,0x2c6f0,0x3ebe8} },
87         { SPOOLSS_FORM_BUILTIN, "B5 (JIS)",                       {0x2c6f0,0x3ebe8}, {0x0,0x0,0x2c6f0,0x3ebe8} },
88         { SPOOLSS_FORM_BUILTIN, "B6 (JIS) Rotated",               {0x2c6f0,0x1f400}, {0x0,0x0,0x2c6f0,0x1f400} },
89         { SPOOLSS_FORM_BUILTIN, "B6 (JIS)",                       {0x1f400,0x2c6f0}, {0x0,0x0,0x1f400,0x2c6f0} },
90         { SPOOLSS_FORM_BUILTIN, "C size sheet",                   {0x696b8,0x886d0}, {0x0,0x0,0x696b8,0x886d0} },
91         { SPOOLSS_FORM_BUILTIN, "D size sheet",                   {0x886d0,0xd2d70}, {0x0,0x0,0x886d0,0xd2d70} },
92         { SPOOLSS_FORM_BUILTIN, "Double Japan Postcard Rotated",  {0x24220,0x30d40}, {0x0,0x0,0x24220,0x30d40} },
93         { SPOOLSS_FORM_BUILTIN, "E size sheet",                   {0xd2d70,0x110da0},{0x0,0x0,0xd2d70,0x110da0} },
94         { SPOOLSS_FORM_BUILTIN, "Envelope #10",                   {0x19947,0x3ae94}, {0x0,0x0,0x19947,0x3ae94} },
95         { SPOOLSS_FORM_BUILTIN, "Envelope #11",                   {0x1be7c,0x40565}, {0x0,0x0,0x1be7c,0x40565} },
96         { SPOOLSS_FORM_BUILTIN, "Envelope #12",                   {0x1d74a,0x44368}, {0x0,0x0,0x1d74a,0x44368} },
97         { SPOOLSS_FORM_BUILTIN, "Envelope #14",                   {0x1f018,0x47504}, {0x0,0x0,0x1f018,0x47504} },
98         { SPOOLSS_FORM_BUILTIN, "Envelope #9",                    {0x18079,0x37091}, {0x0,0x0,0x18079,0x37091} },
99         { SPOOLSS_FORM_BUILTIN, "Envelope B4",                    {0x3d090,0x562e8}, {0x0,0x0,0x3d090,0x562e8} },
100         { SPOOLSS_FORM_BUILTIN, "Envelope B5",                    {0x2af80,0x3d090}, {0x0,0x0,0x2af80,0x3d090} },
101         { SPOOLSS_FORM_BUILTIN, "Envelope B6",                    {0x2af80,0x1e848}, {0x0,0x0,0x2af80,0x1e848} },
102         { SPOOLSS_FORM_BUILTIN, "Envelope C3",                    {0x4f1a0,0x6fd10}, {0x0,0x0,0x4f1a0,0x6fd10} },
103         { SPOOLSS_FORM_BUILTIN, "Envelope C4",                    {0x37e88,0x4f1a0}, {0x0,0x0,0x37e88,0x4f1a0} },
104         { SPOOLSS_FORM_BUILTIN, "Envelope C5",                    {0x278d0,0x37e88}, {0x0,0x0,0x278d0,0x37e88} },
105         { SPOOLSS_FORM_BUILTIN, "Envelope C6",                    {0x1bd50,0x278d0}, {0x0,0x0,0x1bd50,0x278d0} },
106         { SPOOLSS_FORM_BUILTIN, "Envelope C65",                   {0x1bd50,0x37e88}, {0x0,0x0,0x1bd50,0x37e88} },
107         { SPOOLSS_FORM_BUILTIN, "Envelope DL",                    {0x1adb0,0x35b60}, {0x0,0x0,0x1adb0,0x35b60} },
108         { SPOOLSS_FORM_BUILTIN, "Envelope Invite",                {0x35b60,0x35b60}, {0x0,0x0,0x35b60,0x35b60} },
109         { SPOOLSS_FORM_BUILTIN, "Envelope Monarch",               {0x18079,0x2e824}, {0x0,0x0,0x18079,0x2e824} },
110         { SPOOLSS_FORM_BUILTIN, "Envelope",                       {0x1adb0,0x38270}, {0x0,0x0,0x1adb0,0x38270} },
111         { SPOOLSS_FORM_BUILTIN, "Executive",                      {0x2cf56,0x411cc}, {0x0,0x0,0x2cf56,0x411cc} },
112         { SPOOLSS_FORM_BUILTIN, "Folio",                          {0x34b5c,0x509d8}, {0x0,0x0,0x34b5c,0x509d8} },
113         { SPOOLSS_FORM_BUILTIN, "German Legal Fanfold",           {0x34b5c,0x509d8}, {0x0,0x0,0x34b5c,0x509d8} },
114         { SPOOLSS_FORM_BUILTIN, "German Std Fanfold",             {0x34b5c,0x4a6a0}, {0x0,0x0,0x34b5c,0x4a6a0} },
115         { SPOOLSS_FORM_BUILTIN, "Japan Envelope Chou #3 Rotated", {0x395f8,0x1d4c0}, {0x0,0x0,0x395f8,0x1d4c0} },
116         { SPOOLSS_FORM_BUILTIN, "Japan Envelope Chou #4 Rotated", {0x320c8,0x15f90}, {0x0,0x0,0x320c8,0x15f90} },
117         { SPOOLSS_FORM_BUILTIN, "Japan Envelope Kaku #2 Rotated", {0x510e0,0x3a980}, {0x0,0x0,0x510e0,0x3a980} },
118         { SPOOLSS_FORM_BUILTIN, "Japan Envelope Kaku #3 Rotated", {0x43a08,0x34bc0}, {0x0,0x0,0x43a08,0x34bc0} },
119         { SPOOLSS_FORM_BUILTIN, "Japan Envelope You #4 Rotated",  {0x395f8,0x19a28}, {0x0,0x0,0x395f8,0x19a28} },
120         { SPOOLSS_FORM_BUILTIN, "Japan Envelope You #4",          {0x19a28,0x395f8}, {0x0,0x0,0x19a28,0x395f8} },
121         { SPOOLSS_FORM_BUILTIN, "Japanese Double Postcard",       {0x30d40,0x24220}, {0x0,0x0,0x30d40,0x24220} },
122         { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Chou #3",      {0x1d4c0,0x395f8}, {0x0,0x0,0x1d4c0,0x395f8} },
123         { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Chou #4",      {0x15f90,0x320c8}, {0x0,0x0,0x15f90,0x320c8} },
124         { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Kaku #2",      {0x3a980,0x510e0}, {0x0,0x0,0x3a980,0x510e0} },
125         { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Kaku #3",      {0x34bc0,0x43a08}, {0x0,0x0,0x34bc0,0x43a08} },
126         { SPOOLSS_FORM_BUILTIN, "Japanese Postcard Rotated",      {0x24220,0x186a0}, {0x0,0x0,0x24220,0x186a0} },
127         { SPOOLSS_FORM_BUILTIN, "Japanese Postcard",              {0x186a0,0x24220}, {0x0,0x0,0x186a0,0x24220} },
128         { SPOOLSS_FORM_BUILTIN, "Ledger",                         {0x696b8,0x44368}, {0x0,0x0,0x696b8,0x44368} },
129         { SPOOLSS_FORM_BUILTIN, "Legal Extra",                    {0x3ae94,0x5d048}, {0x0,0x0,0x3ae94,0x5d048} },
130         { SPOOLSS_FORM_BUILTIN, "Legal",                          {0x34b5c,0x56d10}, {0x0,0x0,0x34b5c,0x56d10} },
131         { SPOOLSS_FORM_BUILTIN, "Letter Extra Transverse",        {0x3ae94,0x4a6a0}, {0x0,0x0,0x3ae94,0x4a6a0} },
132         { SPOOLSS_FORM_BUILTIN, "Letter Extra",                   {0x3ae94,0x4a6a0}, {0x0,0x0,0x3ae94,0x4a6a0} },
133         { SPOOLSS_FORM_BUILTIN, "Letter Plus",                    {0x34b5c,0x4eb16}, {0x0,0x0,0x34b5c,0x4eb16} },
134         { SPOOLSS_FORM_BUILTIN, "Letter Rotated",                 {0x44368,0x34b5c}, {0x0,0x0,0x44368,0x34b5c} },
135         { SPOOLSS_FORM_BUILTIN, "Letter Small",                   {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
136         { SPOOLSS_FORM_BUILTIN, "Letter Transverse",              {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
137         { SPOOLSS_FORM_BUILTIN, "Letter",                         {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
138         { SPOOLSS_FORM_BUILTIN, "Note",                           {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
139         { SPOOLSS_FORM_BUILTIN, "PRC 16K Rotated",                {0x3f7a0,0x2de60}, {0x0,0x0,0x3f7a0,0x2de60} },
140         { SPOOLSS_FORM_BUILTIN, "PRC 16K",                        {0x2de60,0x3f7a0}, {0x0,0x0,0x2de60,0x3f7a0} },
141         { SPOOLSS_FORM_BUILTIN, "PRC 32K Rotated",                {0x2cec0,0x1fbd0}, {0x0,0x0,0x2cec0,0x1fbd0} },
142         { SPOOLSS_FORM_BUILTIN, "PRC 32K",                        {0x1fbd0,0x2cec0}, {0x0,0x0,0x1fbd0,0x2cec0} },
143         { SPOOLSS_FORM_BUILTIN, "PRC 32K(Big) Rotated",           {0x318f8,0x222e0}, {0x0,0x0,0x318f8,0x222e0} },
144         { SPOOLSS_FORM_BUILTIN, "PRC 32K(Big)",                   {0x222e0,0x318f8}, {0x0,0x0,0x222e0,0x318f8} },
145         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #1 Rotated",        {0x28488,0x18e70}, {0x0,0x0,0x28488,0x18e70} },
146         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #1",                {0x18e70,0x28488}, {0x0,0x0,0x18e70,0x28488} },
147         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #10 Rotated",       {0x6fd10,0x4f1a0}, {0x0,0x0,0x6fd10,0x4f1a0} },
148         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #10",               {0x4f1a0,0x6fd10}, {0x0,0x0,0x4f1a0,0x6fd10} },
149         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #2 Rotated",        {0x2af80,0x18e70}, {0x0,0x0,0x2af80,0x18e70} },
150         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #2",                {0x18e70,0x2af80}, {0x0,0x0,0x18e70,0x2af80} },
151         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #3 Rotated",        {0x2af80,0x1e848}, {0x0,0x0,0x2af80,0x1e848} },
152         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #3",                {0x1e848,0x2af80}, {0x0,0x0,0x1e848,0x2af80} },
153         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #4 Rotated",        {0x32c80,0x1adb0}, {0x0,0x0,0x32c80,0x1adb0} },
154         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #4",                {0x1adb0,0x32c80}, {0x0,0x0,0x1adb0,0x32c80} },
155         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #5 Rotated",        {0x35b60,0x1adb0}, {0x0,0x0,0x35b60,0x1adb0} },
156         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #5",                {0x1adb0,0x35b60}, {0x0,0x0,0x1adb0,0x35b60} },
157         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #6 Rotated",        {0x38270,0x1d4c0}, {0x0,0x0,0x38270,0x1d4c0} },
158         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #6",                {0x1d4c0,0x38270}, {0x0,0x0,0x1d4c0,0x38270} },
159         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #7 Rotated",        {0x38270,0x27100}, {0x0,0x0,0x38270,0x27100} },
160         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #7",                {0x27100,0x38270}, {0x0,0x0,0x27100,0x38270} },
161         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #8 Rotated",        {0x4b708,0x1d4c0}, {0x0,0x0,0x4b708,0x1d4c0} },
162         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #8",                {0x1d4c0,0x4b708}, {0x0,0x0,0x1d4c0,0x4b708} },
163         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #9 Rotated",        {0x4f1a0,0x37e88}, {0x0,0x0,0x4f1a0,0x37e88} },
164         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #9",                {0x37e88,0x4f1a0}, {0x0,0x0,0x37e88,0x4f1a0} },
165         { SPOOLSS_FORM_BUILTIN, "Quarto",                         {0x347d8,0x43238}, {0x0,0x0,0x347d8,0x43238} },
166         { SPOOLSS_FORM_BUILTIN, "Reserved48",                     {0x1,0x1},         {0x0,0x0,0x1,0x1} },
167         { SPOOLSS_FORM_BUILTIN, "Reserved49",                     {0x1,0x1},         {0x0,0x0,0x1,0x1} },
168         { SPOOLSS_FORM_BUILTIN, "Statement",                      {0x221b4,0x34b5c}, {0x0,0x0,0x221b4,0x34b5c} },
169         { SPOOLSS_FORM_BUILTIN, "Super A",                        {0x376b8,0x56ea0}, {0x0,0x0,0x376b8,0x56ea0} },
170         { SPOOLSS_FORM_BUILTIN, "Super B",                        {0x4a768,0x76e58}, {0x0,0x0,0x4a768,0x76e58} },
171         { SPOOLSS_FORM_BUILTIN, "Tabloid Extra",                  {0x4a6a0,0x6f9f0}, {0x0,0x0,0x4a6a0,0x6f9f0} },
172         { SPOOLSS_FORM_BUILTIN, "Tabloid",                        {0x44368,0x696b8}, {0x0,0x0,0x44368,0x696b8} },
173         { SPOOLSS_FORM_BUILTIN, "US Std Fanfold",                 {0x5c3e1,0x44368}, {0x0,0x0,0x5c3e1,0x44368} }
174 };
175
176 /********************************************************************
177  static helper functions
178 ********************************************************************/
179
180 /****************************************************************************
181  Update the changeid time.
182 ****************************************************************************/
183 /**
184  * @internal
185  *
186  * @brief Update the ChangeID time of a printer.
187  *
188  * This is SO NASTY as some drivers need this to change, others need it
189  * static. This value will change every second, and I must hope that this
190  * is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
191  * UTAH ! JRA.
192  *
193  * @return              The ChangeID.
194  */
195 static uint32_t winreg_printer_rev_changeid(void)
196 {
197         struct timeval tv;
198
199         get_process_uptime(&tv);
200
201 #if 1   /* JERRY */
202         /* Return changeid as msec since spooler restart */
203         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
204 #else
205         /*
206          * This setting seems to work well but is too untested
207          * to replace the above calculation.  Left in for experiementation
208          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
209          */
210         return tv.tv_sec * 10 + tv.tv_usec / 100000;
211 #endif
212 }
213
214 /**
215  * @internal
216  *
217  * @brief Connect to the interal winreg server and open the given printer key.
218  *
219  * The function will create the needed subkeys if they don't exist.
220  *
221  * @param[in]  mem_ctx       The memory context to use.
222  *
223  * @param[in]  server_info   The supplied server info.
224  *
225  * @param[out] winreg_pipe   A pointer for the winreg rpc client pipe.
226  *
227  * @param[in]  path          The path to the key to open.
228  *
229  * @param[in]  key           The key to open.
230  *
231  * @param[in]  create_key    Set to true if the key should be created if it
232  *                           doesn't exist.
233  *
234  * @param[in]  access_mask   The access mask to open the key.
235  *
236  * @param[out] hive_handle   A policy handle for the opened hive.
237  *
238  * @param[out] key_handle    A policy handle for the opened key.
239  *
240  * @return                   WERR_OK on success, the corresponding DOS error
241  *                           code if something gone wrong.
242  */
243 static WERROR winreg_printer_openkey(TALLOC_CTX *mem_ctx,
244                               struct auth_serversupplied_info *server_info,
245                               struct rpc_pipe_client **winreg_pipe,
246                               const char *path,
247                               const char *key,
248                               bool create_key,
249                               uint32_t access_mask,
250                               struct policy_handle *hive_handle,
251                               struct policy_handle *key_handle)
252 {
253         struct rpc_pipe_client *pipe_handle;
254         struct winreg_String wkey, wkeyclass;
255         char *keyname;
256         NTSTATUS status;
257         WERROR result = WERR_OK;
258
259         /* create winreg connection */
260         status = rpc_pipe_open_internal(mem_ctx,
261                                         &ndr_table_winreg.syntax_id,
262                                         server_info,
263                                         &pipe_handle);
264         if (!NT_STATUS_IS_OK(status)) {
265                 DEBUG(0, ("winreg_printer_openkey: Could not connect to winreg_pipe: %s\n",
266                           nt_errstr(status)));
267                 return ntstatus_to_werror(status);
268         }
269
270         status = rpccli_winreg_OpenHKLM(pipe_handle,
271                                         mem_ctx,
272                                         NULL,
273                                         access_mask,
274                                         hive_handle,
275                                         &result);
276         if (!NT_STATUS_IS_OK(status)) {
277                 DEBUG(0, ("winreg_printer_openkey: Could not open HKLM hive: %s\n",
278                           nt_errstr(status)));
279                 talloc_free(pipe_handle);
280                 if (!W_ERROR_IS_OK(result)) {
281                         return result;
282                 }
283                 return ntstatus_to_werror(status);
284         }
285
286         if (key && *key) {
287                 keyname = talloc_asprintf(mem_ctx, "%s\\%s", path, key);
288         } else {
289                 keyname = talloc_strdup(mem_ctx, path);
290         }
291         if (keyname == NULL) {
292                 talloc_free(pipe_handle);
293                 return WERR_NOMEM;
294         }
295
296         ZERO_STRUCT(wkey);
297         wkey.name = keyname;
298
299         if (create_key) {
300                 enum winreg_CreateAction action = REG_ACTION_NONE;
301
302                 ZERO_STRUCT(wkeyclass);
303                 wkeyclass.name = "";
304
305                 status = rpccli_winreg_CreateKey(pipe_handle,
306                                                  mem_ctx,
307                                                  hive_handle,
308                                                  wkey,
309                                                  wkeyclass,
310                                                  0,
311                                                  access_mask,
312                                                  NULL,
313                                                  key_handle,
314                                                  &action,
315                                                  &result);
316                 switch (action) {
317                         case REG_ACTION_NONE:
318                                 DEBUG(8, ("winreg_printer_openkey:createkey did nothing -- huh?\n"));
319                                 break;
320                         case REG_CREATED_NEW_KEY:
321                                 DEBUG(8, ("winreg_printer_openkey: createkey created %s\n", keyname));
322                                 break;
323                         case REG_OPENED_EXISTING_KEY:
324                                 DEBUG(8, ("winreg_printer_openkey: createkey opened existing %s\n", keyname));
325                                 break;
326                 }
327         } else {
328                 status = rpccli_winreg_OpenKey(pipe_handle,
329                                                mem_ctx,
330                                                hive_handle,
331                                                wkey,
332                                                0,
333                                                access_mask,
334                                                key_handle,
335                                                &result);
336         }
337         if (!NT_STATUS_IS_OK(status)) {
338                 talloc_free(pipe_handle);
339                 if (!W_ERROR_IS_OK(result)) {
340                         return result;
341                 }
342                 return ntstatus_to_werror(status);
343         }
344
345         *winreg_pipe = pipe_handle;
346
347         return WERR_OK;
348 }
349
350 /**
351  * @brief Create the registry keyname for the given printer.
352  *
353  * @param[in]  mem_ctx  The memory context to use.
354  *
355  * @param[in]  printer  The name of the printer to get the registry key.
356  *
357  * @return     The registry key or NULL on error.
358  */
359 static char *winreg_printer_data_keyname(TALLOC_CTX *mem_ctx, const char *printer) {
360         return talloc_asprintf(mem_ctx, "%s\\%s", TOP_LEVEL_PRINT_PRINTERS_KEY, printer);
361 }
362
363 /**
364  * @internal
365  *
366  * @brief Enumerate values of an opened key handle and retrieve the data.
367  *
368  * @param[in]  mem_ctx  The memory context to use.
369  *
370  * @param[in]  pipe_handle The pipe handle for the rpc connection.
371  *
372  * @param[in]  key_hnd  The opened key handle.
373  *
374  * @param[out] pnum_values A pointer to store he number of values found.
375  *
376  * @param[out] pnum_values A pointer to store the number of values we found.
377  *
378  * @return                   WERR_OK on success, the corresponding DOS error
379  *                           code if something gone wrong.
380  */
381 static WERROR winreg_printer_enumvalues(TALLOC_CTX *mem_ctx,
382                                         struct rpc_pipe_client *pipe_handle,
383                                         struct policy_handle *key_hnd,
384                                         uint32_t *pnum_values,
385                                         struct spoolss_PrinterEnumValues **penum_values)
386 {
387         TALLOC_CTX *tmp_ctx;
388         uint32_t num_subkeys, max_subkeylen, max_classlen;
389         uint32_t num_values, max_valnamelen, max_valbufsize;
390         uint32_t secdescsize;
391         uint32_t i;
392         NTTIME last_changed_time;
393         struct winreg_String classname;
394
395         struct spoolss_PrinterEnumValues *enum_values;
396
397         WERROR result = WERR_OK;
398         NTSTATUS status;
399
400         tmp_ctx = talloc_stackframe();
401         if (tmp_ctx == NULL) {
402                 return WERR_NOMEM;
403         }
404
405         ZERO_STRUCT(classname);
406
407         status = rpccli_winreg_QueryInfoKey(pipe_handle,
408                                             tmp_ctx,
409                                             key_hnd,
410                                             &classname,
411                                             &num_subkeys,
412                                             &max_subkeylen,
413                                             &max_classlen,
414                                             &num_values,
415                                             &max_valnamelen,
416                                             &max_valbufsize,
417                                             &secdescsize,
418                                             &last_changed_time,
419                                             &result);
420         if (!NT_STATUS_IS_OK(status)) {
421                 DEBUG(0, ("winreg_printer_enumvalues: Could not query info: %s\n",
422                           nt_errstr(status)));
423                 if (!W_ERROR_IS_OK(result)) {
424                         goto error;
425                 }
426                 result = ntstatus_to_werror(status);
427                 goto error;
428         }
429
430         if (num_values == 0) {
431                 *pnum_values = 0;
432                 TALLOC_FREE(tmp_ctx);
433                 return WERR_OK;
434         }
435
436         enum_values = TALLOC_ARRAY(tmp_ctx, struct spoolss_PrinterEnumValues, num_values);
437         if (enum_values == NULL) {
438                 result = WERR_NOMEM;
439                 goto error;
440         }
441
442         for (i = 0; i < num_values; i++) {
443                 struct spoolss_PrinterEnumValues val;
444                 struct winreg_ValNameBuf name_buf;
445                 enum winreg_Type type = REG_NONE;
446                 uint8_t *data;
447                 uint32_t data_size;
448                 uint32_t length;
449                 char n = '\0';;
450
451                 name_buf.name = &n;
452                 name_buf.size = max_valnamelen + 2;
453                 name_buf.length = 0;
454
455                 data_size = max_valbufsize;
456                 data = NULL;
457                 if (data_size) {
458                         data = (uint8_t *) TALLOC(tmp_ctx, data_size);
459                 }
460                 length = 0;
461
462                 status = rpccli_winreg_EnumValue(pipe_handle,
463                                                  tmp_ctx,
464                                                  key_hnd,
465                                                  i,
466                                                  &name_buf,
467                                                  &type,
468                                                  data,
469                                                  data_size ? &data_size : NULL,
470                                                  &length,
471                                                  &result);
472                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
473                         result = WERR_OK;
474                         status = NT_STATUS_OK;
475                         break;
476                 }
477
478                 if (!NT_STATUS_IS_OK(status)) {
479                         DEBUG(0, ("winreg_printer_enumvalues: Could not enumerate values: %s\n",
480                                   nt_errstr(status)));
481                         if (!W_ERROR_IS_OK(result)) {
482                                 goto error;
483                         }
484                         result = ntstatus_to_werror(status);
485                         goto error;
486                 }
487
488                 if (name_buf.name == NULL) {
489                         result = WERR_INVALID_PARAMETER;
490                         goto error;
491                 }
492
493                 val.value_name = talloc_strdup(enum_values, name_buf.name);
494                 if (val.value_name == NULL) {
495                         result = WERR_NOMEM;
496                         goto error;
497                 }
498                 val.value_name_len = strlen_m_term(val.value_name) * 2;
499
500                 val.type = type;
501                 val.data_length = data_size;
502                 val.data = NULL;
503                 if (val.data_length) {
504                         val.data = talloc(enum_values, DATA_BLOB);
505                         if (val.data == NULL) {
506                                 result = WERR_NOMEM;
507                                 goto error;
508                         }
509                         *val.data = data_blob_talloc(enum_values, data, data_size);
510                 }
511
512                 enum_values[i] = val;
513         }
514
515         *pnum_values = num_values;
516         if (penum_values) {
517                 *penum_values = talloc_move(mem_ctx, &enum_values);
518         }
519
520         result = WERR_OK;
521
522  error:
523         TALLOC_FREE(tmp_ctx);
524         return result;
525 }
526
527 /**
528  * @internal
529  *
530  * @brief Enumerate subkeys of an opened key handle and get the names.
531  *
532  * @param[in]  mem_ctx  The memory context to use.
533  *
534  * @param[in]  pipe_handle The pipe handle for the rpc connection.
535  *
536  * @param[in]  key_hnd  The opened key handle.
537  *
538  * @param[in]  pnum_subkeys A pointer to store the number of found subkeys.
539  *
540  * @param[in]  psubkeys A pointer to an array to store the found names of
541  *                      subkeys.
542  *
543  * @return                   WERR_OK on success, the corresponding DOS error
544  *                           code if something gone wrong.
545  */
546 static WERROR winreg_printer_enumkeys(TALLOC_CTX *mem_ctx,
547                                       struct rpc_pipe_client *pipe_handle,
548                                       struct policy_handle *key_hnd,
549                                       uint32_t *pnum_subkeys,
550                                       const char ***psubkeys)
551 {
552         TALLOC_CTX *tmp_ctx;
553         const char **subkeys;
554         uint32_t num_subkeys, max_subkeylen, max_classlen;
555         uint32_t num_values, max_valnamelen, max_valbufsize;
556         uint32_t i;
557         NTTIME last_changed_time;
558         uint32_t secdescsize;
559         struct winreg_String classname;
560         WERROR result = WERR_OK;
561         NTSTATUS status;
562
563         tmp_ctx = talloc_stackframe();
564         if (tmp_ctx == NULL) {
565                 return WERR_NOMEM;
566         }
567
568         ZERO_STRUCT(classname);
569
570         status = rpccli_winreg_QueryInfoKey(pipe_handle,
571                                             tmp_ctx,
572                                             key_hnd,
573                                             &classname,
574                                             &num_subkeys,
575                                             &max_subkeylen,
576                                             &max_classlen,
577                                             &num_values,
578                                             &max_valnamelen,
579                                             &max_valbufsize,
580                                             &secdescsize,
581                                             &last_changed_time,
582                                             &result);
583         if (!NT_STATUS_IS_OK(status)) {
584                 DEBUG(0, ("winreg_printer_enumkeys: Could not query info: %s\n",
585                           nt_errstr(status)));
586                 if (!W_ERROR_IS_OK(result)) {
587                         goto error;
588                 }
589                 result = ntstatus_to_werror(status);
590                 goto error;
591         }
592
593         subkeys = talloc_zero_array(tmp_ctx, const char *, num_subkeys + 2);
594         if (subkeys == NULL) {
595                 result = WERR_NOMEM;
596                 goto error;
597         }
598
599         if (num_subkeys == 0) {
600                 subkeys[0] = talloc_strdup(subkeys, "");
601                 if (subkeys[0] == NULL) {
602                         result = WERR_NOMEM;
603                         goto error;
604                 }
605                 *pnum_subkeys = 0;
606                 if (psubkeys) {
607                         *psubkeys = talloc_move(mem_ctx, &subkeys);
608                 }
609
610                 TALLOC_FREE(tmp_ctx);
611                 return WERR_OK;
612         }
613
614         for (i = 0; i < num_subkeys; i++) {
615                 char c = '\0';
616                 char n = '\0';
617                 char *name = NULL;
618                 struct winreg_StringBuf class_buf;
619                 struct winreg_StringBuf name_buf;
620                 NTTIME modtime;
621
622                 class_buf.name = &c;
623                 class_buf.size = max_classlen + 2;
624                 class_buf.length = 0;
625
626                 name_buf.name = &n;
627                 name_buf.size = max_subkeylen + 2;
628                 name_buf.length = 0;
629
630                 ZERO_STRUCT(modtime);
631
632                 status = rpccli_winreg_EnumKey(pipe_handle,
633                                                tmp_ctx,
634                                                key_hnd,
635                                                i,
636                                                &name_buf,
637                                                &class_buf,
638                                                &modtime,
639                                                &result);
640                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
641                         result = WERR_OK;
642                         status = NT_STATUS_OK;
643                         break;
644                 }
645
646                 if (!NT_STATUS_IS_OK(status)) {
647                         DEBUG(0, ("winreg_printer_enumkeys: Could not enumerate keys: %s\n",
648                                   nt_errstr(status)));
649                         if (!W_ERROR_IS_OK(result)) {
650                                 goto error;
651                         }
652                         result = ntstatus_to_werror(status);
653                         goto error;
654                 }
655
656                 if (name_buf.name == NULL) {
657                         result = WERR_INVALID_PARAMETER;
658                         goto error;
659                 }
660
661                 name = talloc_strdup(subkeys, name_buf.name);
662                 if (name == NULL) {
663                         result = WERR_NOMEM;
664                         goto error;
665                 }
666
667                 subkeys[i] = name;
668         }
669
670         *pnum_subkeys = num_subkeys;
671         if (psubkeys) {
672                 *psubkeys = talloc_move(mem_ctx, &subkeys);
673         }
674
675  error:
676         TALLOC_FREE(tmp_ctx);
677         return result;
678 }
679
680 /**
681  * @internal
682  *
683  * @brief A function to delete a key and its subkeys recurively.
684  *
685  * @param[in]  mem_ctx  The memory context to use.
686  *
687  * @param[in]  pipe_handle The pipe handle for the rpc connection.
688  *
689  * @param[in]  hive_handle A opened hive handle to the key.
690  *
691  * @param[in]  access_mask The access mask to access the key.
692  *
693  * @param[in]  key      The key to delete
694  *
695  * @return              WERR_OK on success, the corresponding DOS error
696  *                      code if something gone wrong.
697  */
698 static WERROR winreg_printer_delete_subkeys(TALLOC_CTX *mem_ctx,
699                                             struct rpc_pipe_client *pipe_handle,
700                                             struct policy_handle *hive_handle,
701                                             uint32_t access_mask,
702                                             const char *key)
703 {
704         const char **subkeys = NULL;
705         uint32_t num_subkeys = 0;
706         struct policy_handle key_hnd;
707         struct winreg_String wkey;
708         WERROR result = WERR_OK;
709         NTSTATUS status;
710         uint32_t i;
711
712         ZERO_STRUCT(key_hnd);
713         wkey.name = key;
714
715         DEBUG(2, ("winreg_printer_delete_subkeys: delete key %s\n", key));
716         /* open the key */
717         status = rpccli_winreg_OpenKey(pipe_handle,
718                                        mem_ctx,
719                                        hive_handle,
720                                        wkey,
721                                        0,
722                                        access_mask,
723                                        &key_hnd,
724                                        &result);
725         if (!NT_STATUS_IS_OK(status)) {
726                 DEBUG(0, ("winreg_printer_delete_subkeys: Could not open key %s: %s\n",
727                           wkey.name, nt_errstr(status)));
728                 if (!W_ERROR_IS_OK(result)) {
729                         return result;
730                 }
731                 return ntstatus_to_werror(status);
732         }
733
734         result = winreg_printer_enumkeys(mem_ctx,
735                                          pipe_handle,
736                                          &key_hnd,
737                                          &num_subkeys,
738                                          &subkeys);
739         if (!W_ERROR_IS_OK(result)) {
740                 goto done;
741         }
742
743         for (i = 0; i < num_subkeys; i++) {
744                 /* create key + subkey */
745                 char *subkey = talloc_asprintf(mem_ctx, "%s\\%s", key, subkeys[i]);
746                 if (subkey == NULL) {
747                         goto done;
748                 }
749
750                 DEBUG(2, ("winreg_printer_delete_subkeys: delete subkey %s\n", subkey));
751                 result = winreg_printer_delete_subkeys(mem_ctx,
752                                                        pipe_handle,
753                                                        hive_handle,
754                                                        access_mask,
755                                                        subkey);
756                 if (!W_ERROR_IS_OK(result)) {
757                         goto done;
758                 }
759         }
760
761         if (is_valid_policy_hnd(&key_hnd)) {
762                 rpccli_winreg_CloseKey(pipe_handle, mem_ctx, &key_hnd, NULL);
763         }
764
765         wkey.name = key;
766
767         status = rpccli_winreg_DeleteKey(pipe_handle,
768                                          mem_ctx,
769                                          hive_handle,
770                                          wkey,
771                                          &result);
772
773 done:
774         if (is_valid_policy_hnd(&key_hnd)) {
775                 rpccli_winreg_CloseKey(pipe_handle, mem_ctx, &key_hnd, NULL);
776         }
777
778         return result;
779 }
780
781 static WERROR winreg_printer_write_sz(TALLOC_CTX *mem_ctx,
782                                       struct rpc_pipe_client *pipe_handle,
783                                       struct policy_handle *key_handle,
784                                       const char *value,
785                                       const char *data)
786 {
787         struct winreg_String wvalue;
788         DATA_BLOB blob;
789         WERROR result = WERR_OK;
790         NTSTATUS status;
791
792         wvalue.name = value;
793         if (data == NULL) {
794                 blob = data_blob_string_const("");
795         } else {
796                 if (!push_reg_sz(mem_ctx, &blob, data)) {
797                         DEBUG(0, ("winreg_printer_write_sz: Could not marshall string %s for %s\n",
798                                 data, wvalue.name));
799                         return WERR_NOMEM;
800                 }
801         }
802         status = rpccli_winreg_SetValue(pipe_handle,
803                                         mem_ctx,
804                                         key_handle,
805                                         wvalue,
806                                         REG_SZ,
807                                         blob.data,
808                                         blob.length,
809                                         &result);
810         if (!NT_STATUS_IS_OK(status)) {
811                 DEBUG(0, ("winreg_printer_write_sz: Could not set value %s: %s\n",
812                         wvalue.name, win_errstr(result)));
813                 if (!W_ERROR_IS_OK(result)) {
814                         result = ntstatus_to_werror(status);
815                 }
816         }
817
818         return result;
819 }
820
821 static WERROR winreg_printer_write_dword(TALLOC_CTX *mem_ctx,
822                                          struct rpc_pipe_client *pipe_handle,
823                                          struct policy_handle *key_handle,
824                                          const char *value,
825                                          uint32_t data)
826 {
827         struct winreg_String wvalue;
828         DATA_BLOB blob;
829         WERROR result = WERR_OK;
830         NTSTATUS status;
831
832         wvalue.name = value;
833         blob = data_blob_talloc(mem_ctx, NULL, 4);
834         SIVAL(blob.data, 0, data);
835
836         status = rpccli_winreg_SetValue(pipe_handle,
837                                         mem_ctx,
838                                         key_handle,
839                                         wvalue,
840                                         REG_DWORD,
841                                         blob.data,
842                                         blob.length,
843                                         &result);
844         if (!NT_STATUS_IS_OK(status)) {
845                 DEBUG(0, ("winreg_printer_write_dword: Could not set value %s: %s\n",
846                         wvalue.name, win_errstr(result)));
847                 if (!W_ERROR_IS_OK(result)) {
848                         result = ntstatus_to_werror(status);
849                 }
850         }
851
852         return result;
853 }
854
855 static WERROR winreg_printer_write_binary(TALLOC_CTX *mem_ctx,
856                                           struct rpc_pipe_client *pipe_handle,
857                                           struct policy_handle *key_handle,
858                                           const char *value,
859                                           DATA_BLOB blob)
860 {
861         struct winreg_String wvalue;
862         WERROR result = WERR_OK;
863         NTSTATUS status;
864
865         wvalue.name = value;
866         status = rpccli_winreg_SetValue(pipe_handle,
867                                         mem_ctx,
868                                         key_handle,
869                                         wvalue,
870                                         REG_BINARY,
871                                         blob.data,
872                                         blob.length,
873                                         &result);
874         if (!NT_STATUS_IS_OK(status)) {
875                 DEBUG(0, ("winreg_printer_write_binary: Could not set value %s: %s\n",
876                         wvalue.name, win_errstr(result)));
877                 if (!W_ERROR_IS_OK(result)) {
878                         result = ntstatus_to_werror(status);
879                 }
880         }
881
882         return result;
883 }
884
885 static WERROR winreg_printer_query_binary(TALLOC_CTX *mem_ctx,
886                                           struct rpc_pipe_client *pipe_handle,
887                                           struct policy_handle *key_handle,
888                                           const char *value,
889                                           DATA_BLOB *data)
890 {
891         struct winreg_String wvalue;
892         enum winreg_Type type;
893         WERROR result = WERR_OK;
894         uint32_t value_len = 0;
895         uint32_t data_size = 0;
896         NTSTATUS status;
897         DATA_BLOB blob;
898
899         wvalue.name = value;
900         status = rpccli_winreg_QueryValue(pipe_handle,
901                                           mem_ctx,
902                                           key_handle,
903                                           &wvalue,
904                                           &type,
905                                           NULL,
906                                           &data_size,
907                                           &value_len,
908                                           &result);
909         if (!NT_STATUS_IS_OK(status)) {
910                 DEBUG(2, ("winreg_printer_query_binary: Could not query value %s: %s\n",
911                           wvalue.name, nt_errstr(status)));
912                 if (!W_ERROR_IS_OK(result)) {
913                         goto done;
914                 }
915                 result = ntstatus_to_werror(status);
916                 goto done;
917         }
918
919         if (type != REG_BINARY) {
920                 result = WERR_INVALID_DATATYPE;
921                 goto done;
922         }
923         blob = data_blob_talloc(mem_ctx, NULL, data_size);
924         if (blob.data == NULL) {
925                 result = WERR_NOMEM;
926                 goto done;
927         }
928         value_len = 0;
929
930         status = rpccli_winreg_QueryValue(pipe_handle,
931                                           mem_ctx,
932                                           key_handle,
933                                           &wvalue,
934                                           &type,
935                                           blob.data,
936                                           &data_size,
937                                           &value_len,
938                                           &result);
939         if (!NT_STATUS_IS_OK(status)) {
940                 DEBUG(2, ("winreg_printer_query_binary: Could not query value %s: %s\n",
941                           wvalue.name, nt_errstr(status)));
942                 if (!W_ERROR_IS_OK(result)) {
943                         result = ntstatus_to_werror(status);
944                 }
945                 goto done;
946         }
947
948         if (data) {
949                 data->data = blob.data;
950                 data->length = blob.length;
951         }
952 done:
953         return result;
954 }
955
956 static WERROR winreg_printer_query_dword(TALLOC_CTX *mem_ctx,
957                                          struct rpc_pipe_client *pipe_handle,
958                                          struct policy_handle *key_handle,
959                                          const char *value,
960                                          uint32_t *data)
961 {
962         struct winreg_String wvalue;
963         enum winreg_Type type;
964         WERROR result = WERR_OK;
965         uint32_t value_len = 0;
966         uint32_t data_size = 0;
967         NTSTATUS status;
968         DATA_BLOB blob;
969
970         wvalue.name = value;
971         status = rpccli_winreg_QueryValue(pipe_handle,
972                                           mem_ctx,
973                                           key_handle,
974                                           &wvalue,
975                                           &type,
976                                           NULL,
977                                           &data_size,
978                                           &value_len,
979                                           &result);
980         if (!NT_STATUS_IS_OK(status)) {
981                 DEBUG(2, ("winreg_printer_query_dword: Could not query value %s: %s\n",
982                           wvalue.name, nt_errstr(status)));
983                 if (!W_ERROR_IS_OK(result)) {
984                         goto done;
985                 }
986                 result = ntstatus_to_werror(status);
987                 goto done;
988         }
989
990         if (type != REG_DWORD) {
991                 result = WERR_INVALID_DATATYPE;
992                 goto done;
993         }
994
995         if (data_size != 4) {
996                 result = WERR_INVALID_DATA;
997                 goto done;
998         }
999
1000         blob = data_blob_talloc(mem_ctx, NULL, data_size);
1001         if (blob.data == NULL) {
1002                 result = WERR_NOMEM;
1003                 goto done;
1004         }
1005         value_len = 0;
1006
1007         status = rpccli_winreg_QueryValue(pipe_handle,
1008                                           mem_ctx,
1009                                           key_handle,
1010                                           &wvalue,
1011                                           &type,
1012                                           blob.data,
1013                                           &data_size,
1014                                           &value_len,
1015                                           &result);
1016         if (!NT_STATUS_IS_OK(status)) {
1017                 DEBUG(2, ("winreg_printer_query_dword: Could not query value %s: %s\n",
1018                           wvalue.name, nt_errstr(status)));
1019                 if (!W_ERROR_IS_OK(result)) {
1020                         result = ntstatus_to_werror(status);
1021                 }
1022                 goto done;
1023         }
1024
1025         if (data) {
1026                 *data = IVAL(blob.data, 0);
1027         }
1028 done:
1029         return result;
1030 }
1031
1032 static WERROR winreg_printer_write_multi_sz(TALLOC_CTX *mem_ctx,
1033                                             struct rpc_pipe_client *pipe_handle,
1034                                             struct policy_handle *key_handle,
1035                                             const char *value,
1036                                             const char **data)
1037 {
1038         struct winreg_String wvalue;
1039         DATA_BLOB blob;
1040         WERROR result = WERR_OK;
1041         NTSTATUS status;
1042
1043         wvalue.name = value;
1044         if (!push_reg_multi_sz(mem_ctx, &blob, data)) {
1045                 return WERR_NOMEM;
1046         }
1047         status = rpccli_winreg_SetValue(pipe_handle,
1048                                         mem_ctx,
1049                                         key_handle,
1050                                         wvalue,
1051                                         REG_MULTI_SZ,
1052                                         blob.data,
1053                                         blob.length,
1054                                         &result);
1055         if (!NT_STATUS_IS_OK(status)) {
1056                 DEBUG(0, ("winreg_printer_write_multi_sz: Could not set value %s: %s\n",
1057                         wvalue.name, win_errstr(result)));
1058                 if (!W_ERROR_IS_OK(result)) {
1059                         result = ntstatus_to_werror(status);
1060                 }
1061         }
1062
1063         return result;
1064 }
1065
1066 static WERROR winreg_printer_opendriver(TALLOC_CTX *mem_ctx,
1067                                         struct auth_serversupplied_info *server_info,
1068                                         const char *drivername,
1069                                         const char *architecture,
1070                                         uint32_t version,
1071                                         uint32_t access_mask,
1072                                         bool create,
1073                                         struct rpc_pipe_client **winreg_pipe,
1074                                         struct policy_handle *hive_hnd,
1075                                         struct policy_handle *key_hnd)
1076 {
1077         WERROR result;
1078         char *key_name;
1079
1080         key_name = talloc_asprintf(mem_ctx, "%s\\Environments\\%s\\Drivers\\Version-%u",
1081                                    TOP_LEVEL_CONTROL_KEY,
1082                                    architecture, version);
1083         if (!key_name) {
1084                 return WERR_NOMEM;
1085         }
1086
1087         result = winreg_printer_openkey(mem_ctx,
1088                                         server_info,
1089                                         winreg_pipe,
1090                                         key_name,
1091                                         drivername,
1092                                         create,
1093                                         access_mask,
1094                                         hive_hnd,
1095                                         key_hnd);
1096         return result;
1097 }
1098
1099 static WERROR winreg_enumval_to_dword(TALLOC_CTX *mem_ctx,
1100                                       struct spoolss_PrinterEnumValues *v,
1101                                       const char *valuename, uint32_t *dw)
1102 {
1103         /* just return if it is not the one we are looking for */
1104         if (strcmp(valuename, v->value_name) != 0) {
1105                 return WERR_NOT_FOUND;
1106         }
1107
1108         if (v->type != REG_DWORD) {
1109                 return WERR_INVALID_DATATYPE;
1110         }
1111
1112         if (v->data_length == 0) {
1113                 *dw = 0;
1114                 return WERR_OK;
1115         }
1116
1117         *dw = IVAL(v->data->data, 0);
1118         return WERR_OK;
1119 }
1120
1121 static WERROR winreg_enumval_to_sz(TALLOC_CTX *mem_ctx,
1122                                    struct spoolss_PrinterEnumValues *v,
1123                                    const char *valuename, const char **_str)
1124 {
1125         /* just return if it is not the one we are looking for */
1126         if (strcmp(valuename, v->value_name) != 0) {
1127                 return WERR_NOT_FOUND;
1128         }
1129
1130         if (v->type != REG_SZ) {
1131                 return WERR_INVALID_DATATYPE;
1132         }
1133
1134         if (v->data_length == 0) {
1135                 *_str = talloc_strdup(mem_ctx, EMPTY_STRING);
1136                 if (*_str == NULL) {
1137                         return WERR_NOMEM;
1138                 }
1139                 return WERR_OK;
1140         }
1141
1142         if (!pull_reg_sz(mem_ctx, v->data, _str)) {
1143                 return WERR_NOMEM;
1144         }
1145
1146         return WERR_OK;
1147 }
1148
1149 static WERROR winreg_enumval_to_multi_sz(TALLOC_CTX *mem_ctx,
1150                                          struct spoolss_PrinterEnumValues *v,
1151                                          const char *valuename,
1152                                          const char ***array)
1153 {
1154         /* just return if it is not the one we are looking for */
1155         if (strcmp(valuename, v->value_name) != 0) {
1156                 return WERR_NOT_FOUND;
1157         }
1158
1159         if (v->type != REG_MULTI_SZ) {
1160                 return WERR_INVALID_DATATYPE;
1161         }
1162
1163         if (v->data_length == 0) {
1164                 *array = talloc_array(mem_ctx, const char *, 1);
1165                 if (*array == NULL) {
1166                         return WERR_NOMEM;
1167                 }
1168                 *array[0] = NULL;
1169                 return WERR_OK;
1170         }
1171
1172         if (!pull_reg_multi_sz(mem_ctx, v->data, array)) {
1173                 return WERR_NOMEM;
1174         }
1175
1176         return WERR_OK;
1177 }
1178
1179 static WERROR winreg_printer_write_date(TALLOC_CTX *mem_ctx,
1180                                         struct rpc_pipe_client *pipe_handle,
1181                                         struct policy_handle *key_handle,
1182                                         const char *value,
1183                                         NTTIME data)
1184 {
1185         struct winreg_String wvalue;
1186         DATA_BLOB blob;
1187         WERROR result = WERR_OK;
1188         NTSTATUS status;
1189         const char *str;
1190         struct tm *tm;
1191         time_t t;
1192
1193         t = nt_time_to_unix(data);
1194         tm = localtime(&t);
1195         str = talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
1196                               tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
1197         if (!str) {
1198                 return WERR_NOMEM;
1199         }
1200
1201         wvalue.name = value;
1202         if (!push_reg_sz(mem_ctx, &blob, str)) {
1203                 return WERR_NOMEM;
1204         }
1205         status = rpccli_winreg_SetValue(pipe_handle,
1206                                         mem_ctx,
1207                                         key_handle,
1208                                         wvalue,
1209                                         REG_SZ,
1210                                         blob.data,
1211                                         blob.length,
1212                                         &result);
1213         if (!NT_STATUS_IS_OK(status)) {
1214                 DEBUG(0, ("winreg_printer_write_date: Could not set value %s: %s\n",
1215                         wvalue.name, win_errstr(result)));
1216                 if (!W_ERROR_IS_OK(result)) {
1217                         result = ntstatus_to_werror(status);
1218                 }
1219         }
1220
1221         return result;
1222 }
1223
1224 static WERROR winreg_printer_date_to_NTTIME(const char *str, NTTIME *data)
1225 {
1226         struct tm tm;
1227         time_t t;
1228
1229         ZERO_STRUCT(tm);
1230
1231         if (sscanf(str, "%d/%d/%d",
1232                    &tm.tm_mon, &tm.tm_mday, &tm.tm_year) != 3) {
1233                 return WERR_INVALID_PARAMETER;
1234         }
1235         tm.tm_mon -= 1;
1236         tm.tm_year -= 1900;
1237         tm.tm_isdst = -1;
1238
1239         t = mktime(&tm);
1240         unix_to_nt_time(data, t);
1241
1242         return WERR_OK;
1243 }
1244
1245 static WERROR winreg_printer_write_ver(TALLOC_CTX *mem_ctx,
1246                                        struct rpc_pipe_client *pipe_handle,
1247                                        struct policy_handle *key_handle,
1248                                        const char *value,
1249                                        uint64_t data)
1250 {
1251         struct winreg_String wvalue;
1252         DATA_BLOB blob;
1253         WERROR result = WERR_OK;
1254         NTSTATUS status;
1255         char *str;
1256
1257         /* FIXME: check format is right,
1258          *      this needs to be something like: 6.1.7600.16385 */
1259         str = talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
1260                               (unsigned)((data >> 48) & 0xFFFF),
1261                               (unsigned)((data >> 32) & 0xFFFF),
1262                               (unsigned)((data >> 16) & 0xFFFF),
1263                               (unsigned)(data & 0xFFFF));
1264         if (!str) {
1265                 return WERR_NOMEM;
1266         }
1267
1268         wvalue.name = value;
1269         if (!push_reg_sz(mem_ctx, &blob, str)) {
1270                 return WERR_NOMEM;
1271         }
1272         status = rpccli_winreg_SetValue(pipe_handle,
1273                                         mem_ctx,
1274                                         key_handle,
1275                                         wvalue,
1276                                         REG_SZ,
1277                                         blob.data,
1278                                         blob.length,
1279                                         &result);
1280         if (!NT_STATUS_IS_OK(status)) {
1281                 DEBUG(0, ("winreg_printer_write_date: Could not set value %s: %s\n",
1282                         wvalue.name, win_errstr(result)));
1283                 if (!W_ERROR_IS_OK(result)) {
1284                         result = ntstatus_to_werror(status);
1285                 }
1286         }
1287
1288         return result;
1289 }
1290
1291 static WERROR winreg_printer_ver_to_dword(const char *str, uint64_t *data)
1292 {
1293         unsigned int v1, v2, v3, v4;
1294
1295         if (sscanf(str, "%u.%u.%u.%u", &v1, &v2, &v3, &v4) != 4) {
1296                 return WERR_INVALID_PARAMETER;
1297         }
1298
1299         *data = ((uint64_t)(v1 & 0xFFFF) << 48) +
1300                 ((uint64_t)(v2 & 0xFFFF) << 32) +
1301                 ((uint64_t)(v3 & 0xFFFF) << 16) +
1302                 (uint64_t)(v2 & 0xFFFF);
1303
1304         return WERR_OK;
1305 }
1306
1307 /********************************************************************
1308  Public winreg function for spoolss
1309 ********************************************************************/
1310
1311 WERROR winreg_create_printer(TALLOC_CTX *mem_ctx,
1312                              struct auth_serversupplied_info *server_info,
1313                              const char *servername,
1314                              const char *sharename)
1315 {
1316         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1317         struct rpc_pipe_client *winreg_pipe = NULL;
1318         struct policy_handle hive_hnd, key_hnd;
1319         struct spoolss_SetPrinterInfo2 *info2;
1320         struct security_descriptor *secdesc;
1321         struct winreg_String wkey, wkeyclass;
1322         const char *path;
1323         const char *subkeys[] = { SPOOL_DSDRIVER_KEY, SPOOL_DSSPOOLER_KEY, SPOOL_PRINTERDATA_KEY };
1324         uint32_t i, count = ARRAY_SIZE(subkeys);
1325         uint32_t info2_mask = 0;
1326         WERROR result = WERR_OK;
1327         TALLOC_CTX *tmp_ctx;
1328
1329         tmp_ctx = talloc_stackframe();
1330         if (tmp_ctx == NULL) {
1331                 return WERR_NOMEM;
1332         }
1333
1334         path = winreg_printer_data_keyname(tmp_ctx, sharename);
1335         if (path == NULL) {
1336                 TALLOC_FREE(tmp_ctx);
1337                 return WERR_NOMEM;
1338         }
1339
1340         ZERO_STRUCT(hive_hnd);
1341         ZERO_STRUCT(key_hnd);
1342
1343         result = winreg_printer_openkey(tmp_ctx,
1344                                         server_info,
1345                                         &winreg_pipe,
1346                                         path,
1347                                         "",
1348                                         false,
1349                                         access_mask,
1350                                         &hive_hnd,
1351                                         &key_hnd);
1352         if (W_ERROR_IS_OK(result)) {
1353                 DEBUG(2, ("winreg_create_printer: Skipping, %s already exists\n", path));
1354                 goto done;
1355         } else if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1356                 DEBUG(2, ("winreg_create_printer: Creating default values in %s\n", path));
1357         } else if (!W_ERROR_IS_OK(result)) {
1358                 DEBUG(0, ("winreg_create_printer: Could not open key %s: %s\n",
1359                         path, win_errstr(result)));
1360                 goto done;
1361         }
1362
1363         /* Create the main key */
1364         result = winreg_printer_openkey(tmp_ctx,
1365                                         server_info,
1366                                         &winreg_pipe,
1367                                         path,
1368                                         "",
1369                                         true,
1370                                         access_mask,
1371                                         &hive_hnd,
1372                                         &key_hnd);
1373         if (!W_ERROR_IS_OK(result)) {
1374                 DEBUG(0, ("winreg_create_printer_keys: Could not create key %s: %s\n",
1375                         path, win_errstr(result)));
1376                 goto done;
1377         }
1378
1379         if (is_valid_policy_hnd(&key_hnd)) {
1380                 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1381         }
1382
1383         /* Create subkeys */
1384         for (i = 0; i < count; i++) {
1385                 NTSTATUS status;
1386                 enum winreg_CreateAction action = REG_ACTION_NONE;
1387
1388                 ZERO_STRUCT(key_hnd);
1389                 ZERO_STRUCT(wkey);
1390
1391                 wkey.name = talloc_asprintf(tmp_ctx, "%s\\%s", path, subkeys[i]);
1392                 if (wkey.name == NULL) {
1393                         result = WERR_NOMEM;
1394                         goto done;
1395                 }
1396
1397                 ZERO_STRUCT(wkeyclass);
1398                 wkeyclass.name = "";
1399
1400                 status = rpccli_winreg_CreateKey(winreg_pipe,
1401                                                  tmp_ctx,
1402                                                  &hive_hnd,
1403                                                  wkey,
1404                                                  wkeyclass,
1405                                                  0,
1406                                                  access_mask,
1407                                                  NULL,
1408                                                  &key_hnd,
1409                                                  &action,
1410                                                  &result);
1411                 if (!NT_STATUS_IS_OK(status)) {
1412                         DEBUG(0, ("winreg_create_printer_keys: Could not create key %s: %s\n",
1413                                 wkey.name, win_errstr(result)));
1414                         if (!W_ERROR_IS_OK(result)) {
1415                                 result = ntstatus_to_werror(status);
1416                         }
1417                         goto done;
1418                 }
1419
1420                 switch (i) {
1421                 case 1: {
1422                         const char *dnssuffix;
1423                         const char *longname;
1424                         const char *uncname;
1425
1426                         result = winreg_printer_write_sz(tmp_ctx,
1427                                                          winreg_pipe,
1428                                                          &key_hnd,
1429                                                          SPOOL_REG_PRINTERNAME,
1430                                                          sharename);
1431                         if (!W_ERROR_IS_OK(result)) {
1432                                 goto done;
1433                         }
1434
1435                         result = winreg_printer_write_sz(tmp_ctx,
1436                                                          winreg_pipe,
1437                                                          &key_hnd,
1438                                                          SPOOL_REG_SHORTSERVERNAME,
1439                                                          global_myname());
1440                         if (!W_ERROR_IS_OK(result)) {
1441                                 goto done;
1442                         }
1443
1444                         /* We make the assumption that the netbios name
1445                          * is the same as the DNS name since the former
1446                          * will be what we used to join the domain
1447                          */
1448                         dnssuffix = get_mydnsdomname(tmp_ctx);
1449                         if (dnssuffix != NULL && dnssuffix[0] != '\0') {
1450                                 longname = talloc_asprintf(tmp_ctx, "%s.%s", global_myname(), dnssuffix);
1451                         } else {
1452                                 longname = talloc_strdup(tmp_ctx, global_myname());
1453                         }
1454                         if (longname == NULL) {
1455                                 result = WERR_NOMEM;
1456                                 goto done;
1457                         }
1458
1459                         result = winreg_printer_write_sz(tmp_ctx,
1460                                                          winreg_pipe,
1461                                                          &key_hnd,
1462                                                          SPOOL_REG_SERVERNAME,
1463                                                          longname);
1464                         if (!W_ERROR_IS_OK(result)) {
1465                                 goto done;
1466                         }
1467
1468                         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
1469                                                   longname, sharename);
1470                         if (uncname == NULL) {
1471                                 result = WERR_NOMEM;
1472                                 goto done;
1473                         }
1474
1475                         result = winreg_printer_write_sz(tmp_ctx,
1476                                                          winreg_pipe,
1477                                                          &key_hnd,
1478                                                          SPOOL_REG_UNCNAME,
1479                                                          uncname);
1480                         if (!W_ERROR_IS_OK(result)) {
1481                                 goto done;
1482                         }
1483
1484                         result = winreg_printer_write_dword(tmp_ctx,
1485                                                             winreg_pipe,
1486                                                             &key_hnd,
1487                                                             SPOOL_REG_VERSIONNUMBER,
1488                                                             4);
1489                         if (!W_ERROR_IS_OK(result)) {
1490                                 goto done;
1491                         }
1492
1493                         result = winreg_printer_write_dword(tmp_ctx,
1494                                                             winreg_pipe,
1495                                                             &key_hnd,
1496                                                             SPOOL_REG_PRINTSTARTTIME,
1497                                                             0);
1498                         if (!W_ERROR_IS_OK(result)) {
1499                                 goto done;
1500                         }
1501
1502                         result = winreg_printer_write_dword(tmp_ctx,
1503                                                             winreg_pipe,
1504                                                             &key_hnd,
1505                                                             SPOOL_REG_PRINTENDTIME,
1506                                                             0);
1507                         if (!W_ERROR_IS_OK(result)) {
1508                                 goto done;
1509                         }
1510
1511                         result = winreg_printer_write_dword(tmp_ctx,
1512                                                             winreg_pipe,
1513                                                             &key_hnd,
1514                                                             SPOOL_REG_PRIORITY,
1515                                                             1);
1516                         if (!W_ERROR_IS_OK(result)) {
1517                                 goto done;
1518                         }
1519
1520                         result = winreg_printer_write_dword(tmp_ctx,
1521                                                             winreg_pipe,
1522                                                             &key_hnd,
1523                                                             SPOOL_REG_PRINTKEEPPRINTEDJOBS,
1524                                                             0);
1525                         if (!W_ERROR_IS_OK(result)) {
1526                                 goto done;
1527                         }
1528                 } /* case 1 */
1529                 default:
1530                         break;
1531                 }
1532
1533                 if (is_valid_policy_hnd(&key_hnd)) {
1534                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1535                 }
1536         }
1537         info2 = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
1538         if (info2 == NULL) {
1539                 result = WERR_NOMEM;
1540                 goto done;
1541         }
1542
1543         if (servername != NULL) {
1544                 info2->printername = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
1545                                                      servername, sharename);
1546         } else {
1547                 info2->printername = sharename;
1548         }
1549         if (info2->printername == NULL) {
1550                 result = WERR_NOMEM;
1551                 goto done;
1552         }
1553         info2_mask |= SPOOLSS_PRINTER_INFO_PRINTERNAME;
1554
1555         info2->sharename = sharename;
1556         info2_mask |= SPOOLSS_PRINTER_INFO_SHARENAME;
1557
1558         info2->portname = SAMBA_PRINTER_PORT_NAME;
1559         info2_mask |= SPOOLSS_PRINTER_INFO_PORTNAME;
1560
1561         info2->printprocessor = "winprint";
1562         info2_mask |= SPOOLSS_PRINTER_INFO_PRINTPROCESSOR;
1563
1564         info2->datatype = "RAW";
1565         info2_mask |= SPOOLSS_PRINTER_INFO_DATATYPE;
1566
1567         info2->comment = "";
1568         info2_mask |= SPOOLSS_PRINTER_INFO_COMMENT;
1569
1570         info2->attributes = PRINTER_ATTRIBUTE_SAMBA;
1571         info2_mask |= SPOOLSS_PRINTER_INFO_ATTRIBUTES;
1572
1573         info2->starttime = 0; /* Minutes since 12:00am GMT */
1574         info2_mask |= SPOOLSS_PRINTER_INFO_STARTTIME;
1575
1576         info2->untiltime = 0; /* Minutes since 12:00am GMT */
1577         info2_mask |= SPOOLSS_PRINTER_INFO_UNTILTIME;
1578
1579         info2->priority = 1;
1580         info2_mask |= SPOOLSS_PRINTER_INFO_PRIORITY;
1581
1582         info2->defaultpriority = 1;
1583         info2_mask |= SPOOLSS_PRINTER_INFO_DEFAULTPRIORITY;
1584
1585         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
1586         if (!W_ERROR_IS_OK(result)) {
1587                 goto done;
1588         }
1589         info2_mask |= SPOOLSS_PRINTER_INFO_SECDESC;
1590
1591         /*
1592          * Don't write a default Device Mode to the registry! The Device Mode is
1593          * only written to disk with a SetPrinter level 2 or 8.
1594          */
1595
1596         result = winreg_update_printer(tmp_ctx,
1597                                        server_info,
1598                                        sharename,
1599                                        info2_mask,
1600                                        info2,
1601                                        NULL,
1602                                        secdesc);
1603
1604 done:
1605         if (winreg_pipe != NULL) {
1606                 if (is_valid_policy_hnd(&key_hnd)) {
1607                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1608                 }
1609                 if (is_valid_policy_hnd(&hive_hnd)) {
1610                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1611                 }
1612         }
1613
1614         talloc_free(tmp_ctx);
1615         return result;
1616 }
1617
1618 WERROR winreg_update_printer(TALLOC_CTX *mem_ctx,
1619                              struct auth_serversupplied_info *server_info,
1620                              const char *sharename,
1621                              uint32_t info2_mask,
1622                              struct spoolss_SetPrinterInfo2 *info2,
1623                              struct spoolss_DeviceMode *devmode,
1624                              struct security_descriptor *secdesc)
1625 {
1626         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1627         struct rpc_pipe_client *winreg_pipe = NULL;
1628         struct policy_handle hive_hnd, key_hnd;
1629         int snum = lp_servicenumber(sharename);
1630         enum ndr_err_code ndr_err;
1631         DATA_BLOB blob;
1632         char *path;
1633         WERROR result = WERR_OK;
1634         TALLOC_CTX *tmp_ctx;
1635
1636         tmp_ctx = talloc_stackframe();
1637         if (tmp_ctx == NULL) {
1638                 return WERR_NOMEM;
1639         }
1640
1641         path = winreg_printer_data_keyname(tmp_ctx, sharename);
1642         if (path == NULL) {
1643                 TALLOC_FREE(tmp_ctx);
1644                 return WERR_NOMEM;
1645         }
1646
1647         ZERO_STRUCT(hive_hnd);
1648         ZERO_STRUCT(key_hnd);
1649
1650         result = winreg_printer_openkey(tmp_ctx,
1651                                         server_info,
1652                                         &winreg_pipe,
1653                                         path,
1654                                         "",
1655                                         true,
1656                                         access_mask,
1657                                         &hive_hnd,
1658                                         &key_hnd);
1659         if (!W_ERROR_IS_OK(result)) {
1660                 DEBUG(0, ("winreg_update_printer: Could not open key %s: %s\n",
1661                         path, win_errstr(result)));
1662                 goto done;
1663         }
1664
1665         if (info2_mask & SPOOLSS_PRINTER_INFO_ATTRIBUTES) {
1666                 result = winreg_printer_write_dword(tmp_ctx,
1667                                                     winreg_pipe,
1668                                                     &key_hnd,
1669                                                     "Attributes",
1670                                                     info2->attributes);
1671                 if (!W_ERROR_IS_OK(result)) {
1672                         goto done;
1673                 }
1674         }
1675
1676 #if 0
1677         if (info2_mask & SPOOLSS_PRINTER_INFO_AVERAGEPPM) {
1678                 result = winreg_printer_write_dword(tmp_ctx,
1679                                                     winreg_pipe,
1680                                                     &key_hnd,
1681                                                     "AveragePpm",
1682                                                     info2->attributes);
1683                 if (!W_ERROR_IS_OK(result)) {
1684                         goto done;
1685                 }
1686         }
1687 #endif
1688
1689         if (info2_mask & SPOOLSS_PRINTER_INFO_COMMENT) {
1690                 result = winreg_printer_write_sz(tmp_ctx,
1691                                                  winreg_pipe,
1692                                                  &key_hnd,
1693                                                  "Description",
1694                                                  info2->comment);
1695                 if (!W_ERROR_IS_OK(result)) {
1696                         goto done;
1697                 }
1698         }
1699
1700         if (info2_mask & SPOOLSS_PRINTER_INFO_DATATYPE) {
1701                 result = winreg_printer_write_sz(tmp_ctx,
1702                                                  winreg_pipe,
1703                                                  &key_hnd,
1704                                                  "Datatype",
1705                                                  info2->datatype);
1706                 if (!W_ERROR_IS_OK(result)) {
1707                         goto done;
1708                 }
1709         }
1710
1711         if (info2_mask & SPOOLSS_PRINTER_INFO_DEFAULTPRIORITY) {
1712                 result = winreg_printer_write_dword(tmp_ctx,
1713                                                     winreg_pipe,
1714                                                     &key_hnd,
1715                                                     "Default Priority",
1716                                                     info2->defaultpriority);
1717                 if (!W_ERROR_IS_OK(result)) {
1718                         goto done;
1719                 }
1720         }
1721
1722         if (info2_mask & SPOOLSS_PRINTER_INFO_DEVMODE) {
1723                 /*
1724                  * Some client drivers freak out if there is a NULL devmode
1725                  * (probably the driver is not checking before accessing
1726                  * the devmode pointer)   --jerry
1727                  */
1728                 if (devmode == NULL && lp_default_devmode(snum) && info2 != NULL) {
1729                         result = spoolss_create_default_devmode(tmp_ctx,
1730                                                                 info2->printername,
1731                                                                 &devmode);
1732                         if (!W_ERROR_IS_OK(result)) {
1733                                 goto done;
1734                         }
1735                 }
1736                 ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, devmode,
1737                                 (ndr_push_flags_fn_t) ndr_push_spoolss_DeviceMode);
1738                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1739                         DEBUG(0, ("winreg_update_printer: Failed to marshall device mode\n"));
1740                         result = WERR_NOMEM;
1741                         goto done;
1742                 }
1743
1744                 result = winreg_printer_write_binary(tmp_ctx,
1745                                                      winreg_pipe,
1746                                                      &key_hnd,
1747                                                      "Default DevMode",
1748                                                      blob);
1749                 if (!W_ERROR_IS_OK(result)) {
1750                         goto done;
1751                 }
1752         }
1753
1754         if (info2_mask & SPOOLSS_PRINTER_INFO_DRIVERNAME) {
1755                 result = winreg_printer_write_sz(tmp_ctx,
1756                                                  winreg_pipe,
1757                                                  &key_hnd,
1758                                                  "Printer Driver",
1759                                                  info2->drivername);
1760                 if (!W_ERROR_IS_OK(result)) {
1761                         goto done;
1762                 }
1763         }
1764
1765         if (info2_mask & SPOOLSS_PRINTER_INFO_LOCATION) {
1766                 result = winreg_printer_write_sz(tmp_ctx,
1767                                                  winreg_pipe,
1768                                                  &key_hnd,
1769                                                  "Location",
1770                                                  info2->location);
1771                 if (!W_ERROR_IS_OK(result)) {
1772                         goto done;
1773                 }
1774         }
1775
1776         if (info2_mask & SPOOLSS_PRINTER_INFO_PARAMETERS) {
1777                 result = winreg_printer_write_sz(tmp_ctx,
1778                                                  winreg_pipe,
1779                                                  &key_hnd,
1780                                                  "Parameters",
1781                                                  info2->parameters);
1782                 if (!W_ERROR_IS_OK(result)) {
1783                         goto done;
1784                 }
1785         }
1786
1787         if (info2_mask & SPOOLSS_PRINTER_INFO_PORTNAME) {
1788                 result = winreg_printer_write_sz(tmp_ctx,
1789                                                  winreg_pipe,
1790                                                  &key_hnd,
1791                                                  "Port",
1792                                                  info2->portname);
1793                 if (!W_ERROR_IS_OK(result)) {
1794                         goto done;
1795                 }
1796         }
1797
1798         if (info2_mask & SPOOLSS_PRINTER_INFO_PRINTERNAME) {
1799                 /*
1800                  * in addprinter: no servername and the printer is the name
1801                  * in setprinter: servername is \\server
1802                  *                and printer is \\server\\printer
1803                  *
1804                  * Samba manages only local printers.
1805                  * we currently don't support things like i
1806                  * path=\\other_server\printer
1807                  *
1808                  * We only store the printername, not \\server\printername
1809                  */
1810                 const char *p = strrchr(info2->printername, '\\');
1811                 if (p == NULL) {
1812                         p = info2->printername;
1813                 } else {
1814                         p++;
1815                 }
1816                 result = winreg_printer_write_sz(tmp_ctx,
1817                                                  winreg_pipe,
1818                                                  &key_hnd,
1819                                                  "Name",
1820                                                  p);
1821                 if (!W_ERROR_IS_OK(result)) {
1822                         goto done;
1823                 }
1824         }
1825
1826         if (info2_mask & SPOOLSS_PRINTER_INFO_PRINTPROCESSOR) {
1827                 result = winreg_printer_write_sz(tmp_ctx,
1828                                                  winreg_pipe,
1829                                                  &key_hnd,
1830                                                  "Print Processor",
1831                                                  info2->printprocessor);
1832                 if (!W_ERROR_IS_OK(result)) {
1833                         goto done;
1834                 }
1835         }
1836
1837         if (info2_mask & SPOOLSS_PRINTER_INFO_PRIORITY) {
1838                 result = winreg_printer_write_dword(tmp_ctx,
1839                                                     winreg_pipe,
1840                                                     &key_hnd,
1841                                                     "Priority",
1842                                                     info2->priority);
1843                 if (!W_ERROR_IS_OK(result)) {
1844                         goto done;
1845                 }
1846         }
1847
1848         if (info2_mask & SPOOLSS_PRINTER_INFO_SECDESC) {
1849                 /*
1850                  * We need a security descriptor, if it isn't specified by
1851                  * AddPrinter{Ex} then create a default descriptor.
1852                  */
1853                 if (secdesc == NULL) {
1854                         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
1855                         if (!W_ERROR_IS_OK(result)) {
1856                                 goto done;
1857                         }
1858                 }
1859                 result = winreg_set_printer_secdesc(tmp_ctx,
1860                                                     server_info,
1861                                                     sharename,
1862                                                     secdesc);
1863                 if (!W_ERROR_IS_OK(result)) {
1864                         goto done;
1865                 }
1866         }
1867
1868         if (info2_mask & SPOOLSS_PRINTER_INFO_SEPFILE) {
1869                 result = winreg_printer_write_sz(tmp_ctx,
1870                                                  winreg_pipe,
1871                                                  &key_hnd,
1872                                                  "Separator File",
1873                                                  info2->sepfile);
1874                 if (!W_ERROR_IS_OK(result)) {
1875                         goto done;
1876                 }
1877         }
1878
1879         if (info2_mask & SPOOLSS_PRINTER_INFO_SHARENAME) {
1880                 result = winreg_printer_write_sz(tmp_ctx,
1881                                                  winreg_pipe,
1882                                                  &key_hnd,
1883                                                  "Share Name",
1884                                                  info2->sharename);
1885                 if (!W_ERROR_IS_OK(result)) {
1886                         goto done;
1887                 }
1888         }
1889
1890         if (info2_mask & SPOOLSS_PRINTER_INFO_STARTTIME) {
1891                 result = winreg_printer_write_dword(tmp_ctx,
1892                                                     winreg_pipe,
1893                                                     &key_hnd,
1894                                                     "StartTime",
1895                                                     info2->starttime);
1896                 if (!W_ERROR_IS_OK(result)) {
1897                         goto done;
1898                 }
1899         }
1900
1901         if (info2_mask & SPOOLSS_PRINTER_INFO_STATUS) {
1902                 result = winreg_printer_write_dword(tmp_ctx,
1903                                                     winreg_pipe,
1904                                                     &key_hnd,
1905                                                     "Status",
1906                                                     info2->status);
1907                 if (!W_ERROR_IS_OK(result)) {
1908                         goto done;
1909                 }
1910         }
1911
1912         if (info2_mask & SPOOLSS_PRINTER_INFO_UNTILTIME) {
1913                 result = winreg_printer_write_dword(tmp_ctx,
1914                                                     winreg_pipe,
1915                                                     &key_hnd,
1916                                                     "UntilTime",
1917                                                     info2->untiltime);
1918                 if (!W_ERROR_IS_OK(result)) {
1919                         goto done;
1920                 }
1921         }
1922
1923         result = winreg_printer_write_dword(tmp_ctx,
1924                                             winreg_pipe,
1925                                             &key_hnd,
1926                                             "ChangeID",
1927                                             winreg_printer_rev_changeid());
1928         if (!W_ERROR_IS_OK(result)) {
1929                 goto done;
1930         }
1931
1932         result = WERR_OK;
1933 done:
1934         if (winreg_pipe != NULL) {
1935                 if (is_valid_policy_hnd(&key_hnd)) {
1936                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1937                 }
1938                 if (is_valid_policy_hnd(&hive_hnd)) {
1939                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1940                 }
1941         }
1942
1943         TALLOC_FREE(tmp_ctx);
1944         return result;
1945 }
1946
1947 WERROR winreg_get_printer(TALLOC_CTX *mem_ctx,
1948                           struct auth_serversupplied_info *server_info,
1949                           const char *servername,
1950                           const char *printer,
1951                           struct spoolss_PrinterInfo2 **pinfo2)
1952 {
1953         struct spoolss_PrinterInfo2 *info2;
1954         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1955         struct rpc_pipe_client *winreg_pipe = NULL;
1956         struct policy_handle hive_hnd, key_hnd;
1957         struct spoolss_PrinterEnumValues *enum_values = NULL;
1958         struct spoolss_PrinterEnumValues *v;
1959         enum ndr_err_code ndr_err;
1960         DATA_BLOB blob;
1961         int snum = lp_servicenumber(printer);
1962         uint32_t num_values = 0;
1963         uint32_t i;
1964         char *path;
1965         WERROR result = WERR_OK;
1966         TALLOC_CTX *tmp_ctx;
1967
1968         tmp_ctx = talloc_stackframe();
1969         if (tmp_ctx == NULL) {
1970                 return WERR_NOMEM;
1971         }
1972
1973         path = winreg_printer_data_keyname(tmp_ctx, printer);
1974         if (path == NULL) {
1975                 TALLOC_FREE(tmp_ctx);
1976                 return WERR_NOMEM;
1977         }
1978
1979         result = winreg_printer_openkey(tmp_ctx,
1980                                         server_info,
1981                                         &winreg_pipe,
1982                                         path,
1983                                         "",
1984                                         false,
1985                                         access_mask,
1986                                         &hive_hnd,
1987                                         &key_hnd);
1988         if (!W_ERROR_IS_OK(result)) {
1989                 DEBUG(2, ("winreg_get_printer: Could not open key %s: %s\n",
1990                           path, win_errstr(result)));
1991                 goto done;
1992         }
1993
1994         result = winreg_printer_enumvalues(tmp_ctx,
1995                                            winreg_pipe,
1996                                            &key_hnd,
1997                                            &num_values,
1998                                            &enum_values);
1999         if (!W_ERROR_IS_OK(result)) {
2000                 DEBUG(0, ("winreg_get_printer: Could not enumerate values in %s: %s\n",
2001                           path, win_errstr(result)));
2002                 goto done;
2003         }
2004
2005         info2 = talloc_zero(tmp_ctx, struct spoolss_PrinterInfo2);
2006         if (info2 == NULL) {
2007                 result = WERR_NOMEM;
2008                 goto done;
2009         }
2010
2011         FILL_STRING(info2, EMPTY_STRING, info2->servername);
2012         FILL_STRING(info2, EMPTY_STRING, info2->printername);
2013         FILL_STRING(info2, EMPTY_STRING, info2->sharename);
2014         FILL_STRING(info2, EMPTY_STRING, info2->portname);
2015         FILL_STRING(info2, EMPTY_STRING, info2->drivername);
2016         FILL_STRING(info2, EMPTY_STRING, info2->comment);
2017         FILL_STRING(info2, EMPTY_STRING, info2->location);
2018         FILL_STRING(info2, EMPTY_STRING, info2->sepfile);
2019         FILL_STRING(info2, EMPTY_STRING, info2->printprocessor);
2020         FILL_STRING(info2, EMPTY_STRING, info2->datatype);
2021         FILL_STRING(info2, EMPTY_STRING, info2->parameters);
2022
2023         if (servername != NULL && servername[0] != '\0') {
2024                 info2->servername = talloc_asprintf(info2, "\\\\%s", servername);
2025                 if (info2->servername == NULL) {
2026                         result = WERR_NOMEM;
2027                         goto done;
2028                 }
2029         }
2030
2031         for (i = 0; i < num_values; i++) {
2032                 v = &enum_values[i];
2033
2034                 result = winreg_enumval_to_sz(info2,
2035                                               v,
2036                                               "Name",
2037                                               &info2->printername);
2038                 CHECK_ERROR(result);
2039
2040                 result = winreg_enumval_to_sz(info2,
2041                                               v,
2042                                               "Share Name",
2043                                               &info2->sharename);
2044                 CHECK_ERROR(result);
2045
2046                 result = winreg_enumval_to_sz(info2,
2047                                               v,
2048                                               "Port",
2049                                               &info2->portname);
2050                 CHECK_ERROR(result);
2051
2052                 result = winreg_enumval_to_sz(info2,
2053                                               v,
2054                                               "Description",
2055                                               &info2->comment);
2056                 CHECK_ERROR(result);
2057
2058                 result = winreg_enumval_to_sz(info2,
2059                                               v,
2060                                               "Location",
2061                                               &info2->location);
2062                 CHECK_ERROR(result);
2063
2064                 result = winreg_enumval_to_sz(info2,
2065                                               v,
2066                                               "Separator File",
2067                                               &info2->sepfile);
2068                 CHECK_ERROR(result);
2069
2070                 result = winreg_enumval_to_sz(info2,
2071                                               v,
2072                                               "Print Processor",
2073                                               &info2->printprocessor);
2074                 CHECK_ERROR(result);
2075
2076                 result = winreg_enumval_to_sz(info2,
2077                                               v,
2078                                               "Datatype",
2079                                               &info2->datatype);
2080                 CHECK_ERROR(result);
2081
2082                 result = winreg_enumval_to_sz(info2,
2083                                               v,
2084                                               "Parameters",
2085                                               &info2->parameters);
2086                 CHECK_ERROR(result);
2087
2088                 result = winreg_enumval_to_sz(info2,
2089                                               v,
2090                                               "Printer Driver",
2091                                               &info2->drivername);
2092                 CHECK_ERROR(result);
2093
2094                 result = winreg_enumval_to_dword(info2,
2095                                                  v,
2096                                                  "Attributes",
2097                                                  &info2->attributes);
2098                 CHECK_ERROR(result);
2099
2100                 result = winreg_enumval_to_dword(info2,
2101                                                  v,
2102                                                  "Priority",
2103                                                  &info2->priority);
2104                 CHECK_ERROR(result);
2105
2106                 result = winreg_enumval_to_dword(info2,
2107                                                  v,
2108                                                  "Default Priority",
2109                                                  &info2->defaultpriority);
2110                 CHECK_ERROR(result);
2111
2112                 result = winreg_enumval_to_dword(info2,
2113                                                  v,
2114                                                  "StartTime",
2115                                                  &info2->starttime);
2116                 CHECK_ERROR(result);
2117
2118                 result = winreg_enumval_to_dword(info2,
2119                                                  v,
2120                                                  "UntilTime",
2121                                                  &info2->untiltime);
2122                 CHECK_ERROR(result);
2123
2124                 result = winreg_enumval_to_dword(info2,
2125                                                  v,
2126                                                  "Status",
2127                                                  &info2->status);
2128                 CHECK_ERROR(result);
2129
2130                 result = winreg_enumval_to_dword(info2,
2131                                                  v,
2132                                                  "StartTime",
2133                                                  &info2->starttime);
2134                 CHECK_ERROR(result);
2135         }
2136
2137         if (!W_ERROR_IS_OK(result)) {
2138                 DEBUG(0, ("winreg_get_printer: winreg_enumval_to_TYPE() failed "
2139                                         "for %s: %s\n",
2140                                         v->value_name,
2141                                         win_errstr(result)));
2142                 goto done;
2143         }
2144
2145         /* Create the printername */
2146         if (info2->servername != NULL && info2->servername[0] != '\0') {
2147                 if (lp_force_printername(snum)) {
2148                         const char *p = talloc_asprintf(info2, "%s\\%s",
2149                                                         info2->servername,
2150                                                         info2->sharename);
2151                                 if (p == NULL) {
2152                                         result = WERR_NOMEM;
2153                                         goto done;
2154                                 }
2155                                 info2->printername = p;
2156                 } else {
2157                         char *p = talloc_asprintf(info2, "%s\\%s",
2158                                                   info2->servername,
2159                                                   info2->printername);
2160                         if (p == NULL) {
2161                                 result = WERR_NOMEM;
2162                                 goto done;
2163                         }
2164                         info2->printername = p;
2165                 }
2166         }
2167
2168         /* Construct the Device Mode */
2169         result = winreg_printer_query_binary(tmp_ctx,
2170                                              winreg_pipe,
2171                                              &key_hnd,
2172                                              "Default DevMode",
2173                                              &blob);
2174         if (W_ERROR_IS_OK(result)) {
2175                 info2->devmode = talloc_zero(info2, struct spoolss_DeviceMode);
2176                 if (info2->devmode == NULL) {
2177                         result = WERR_NOMEM;
2178                         goto done;
2179                 }
2180                 ndr_err = ndr_pull_struct_blob(&blob,
2181                                                info2->devmode,
2182                                                info2->devmode,
2183                                                (ndr_pull_flags_fn_t) ndr_pull_spoolss_DeviceMode);
2184                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2185                         DEBUG(0, ("winreg_get_printer: Failed to unmarshall device mode\n"));
2186                         result = WERR_NOMEM;
2187                         goto done;
2188                 }
2189         }
2190
2191         if (info2->devmode == NULL && lp_default_devmode(snum)) {
2192                 result = spoolss_create_default_devmode(info2,
2193                                                         info2->printername,
2194                                                         &info2->devmode);
2195                 if (!W_ERROR_IS_OK(result)) {
2196                         goto done;
2197                 }
2198         }
2199
2200         if (info2->devmode != NULL) {
2201                 info2->devmode->devicename = talloc_strdup(info2->devmode,
2202                                                            info2->printername);
2203                 if (info2->devmode->devicename == NULL) {
2204                         DEBUG(0, ("winreg_get_printer: Failed to set devicename\n"));
2205                         result = WERR_NOMEM;
2206                         goto done;
2207                 }
2208         }
2209
2210         result = winreg_get_printer_secdesc(info2,
2211                                             server_info,
2212                                             printer,
2213                                             &info2->secdesc);
2214         if (!W_ERROR_IS_OK(result)) {
2215                 goto done;
2216         }
2217
2218         /* Fix for OS/2 drivers. */
2219         if (get_remote_arch() == RA_OS2) {
2220                 spoolss_map_to_os2_driver(info2, &info2->drivername);
2221         }
2222
2223         if (pinfo2) {
2224                 *pinfo2 = talloc_move(mem_ctx, &info2);
2225         }
2226
2227         result = WERR_OK;
2228 done:
2229         if (winreg_pipe != NULL) {
2230                 if (is_valid_policy_hnd(&key_hnd)) {
2231                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2232                 }
2233                 if (is_valid_policy_hnd(&hive_hnd)) {
2234                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2235                 }
2236         }
2237
2238         TALLOC_FREE(tmp_ctx);
2239         return result;
2240 }
2241
2242 WERROR winreg_get_printer_secdesc(TALLOC_CTX *mem_ctx,
2243                                   struct auth_serversupplied_info *server_info,
2244                                   const char *sharename,
2245                                   struct spoolss_security_descriptor **psecdesc)
2246 {
2247         struct spoolss_security_descriptor *secdesc;
2248         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2249         struct rpc_pipe_client *winreg_pipe = NULL;
2250         struct policy_handle hive_hnd, key_hnd;
2251         enum ndr_err_code ndr_err;
2252         const char *path;
2253         DATA_BLOB blob;
2254         TALLOC_CTX *tmp_ctx;
2255         WERROR result;
2256
2257         tmp_ctx = talloc_stackframe();
2258         if (tmp_ctx == NULL) {
2259                 return WERR_NOMEM;
2260         }
2261
2262         path = winreg_printer_data_keyname(tmp_ctx, sharename);
2263         if (path == NULL) {
2264                 talloc_free(tmp_ctx);
2265                 return WERR_NOMEM;
2266         }
2267
2268         ZERO_STRUCT(hive_hnd);
2269         ZERO_STRUCT(key_hnd);
2270
2271         result = winreg_printer_openkey(tmp_ctx,
2272                                         server_info,
2273                                         &winreg_pipe,
2274                                         path,
2275                                         "",
2276                                         false,
2277                                         access_mask,
2278                                         &hive_hnd,
2279                                         &key_hnd);
2280         if (!W_ERROR_IS_OK(result)) {
2281                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2282                         goto create_default;
2283                 }
2284                 goto done;
2285         }
2286
2287         result = winreg_printer_query_binary(tmp_ctx,
2288                                              winreg_pipe,
2289                                              &key_hnd,
2290                                              "Security",
2291                                              &blob);
2292         if (!W_ERROR_IS_OK(result)) {
2293                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2294                         goto create_default;
2295                 }
2296                 goto done;
2297         }
2298
2299         secdesc = talloc_zero(tmp_ctx, struct spoolss_security_descriptor);
2300         if (secdesc == NULL) {
2301                 result = WERR_NOMEM;
2302                 goto done;
2303         }
2304         ndr_err = ndr_pull_struct_blob(&blob,
2305                                        secdesc,
2306                                        secdesc,
2307                                        (ndr_pull_flags_fn_t) ndr_pull_security_descriptor);
2308         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2309                 DEBUG(0, ("winreg_get_secdesc: Failed to unmarshall security descriptor\n"));
2310                 result = WERR_NOMEM;
2311                 goto done;
2312         }
2313
2314         if (psecdesc) {
2315                 *psecdesc = talloc_move(mem_ctx, &secdesc);
2316         }
2317
2318         result = WERR_OK;
2319         goto done;
2320
2321 create_default:
2322         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
2323         if (!W_ERROR_IS_OK(result)) {
2324                 return result;
2325         }
2326
2327         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
2328            this security descriptor has been created when winbindd was
2329            down.  Take ownership of security descriptor. */
2330         if (sid_equal(secdesc->owner_sid, &global_sid_World)) {
2331                 struct dom_sid owner_sid;
2332
2333                 /* Change sd owner to workgroup administrator */
2334
2335                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
2336                         struct spoolss_security_descriptor *new_secdesc;
2337                         size_t size;
2338
2339                         /* Create new sd */
2340                         sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
2341
2342                         new_secdesc = make_sec_desc(tmp_ctx,
2343                                                     secdesc->revision,
2344                                                     secdesc->type,
2345                                                     &owner_sid,
2346                                                     secdesc->group_sid,
2347                                                     secdesc->sacl,
2348                                                     secdesc->dacl,
2349                                                     &size);
2350
2351                         if (new_secdesc == NULL) {
2352                                 result = WERR_NOMEM;
2353                                 goto done;
2354                         }
2355
2356                         /* Swap with other one */
2357                         secdesc = new_secdesc;
2358                 }
2359         }
2360
2361         ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, secdesc,
2362                         (ndr_push_flags_fn_t) ndr_push_security_descriptor);
2363         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2364                 DEBUG(0, ("winreg_set_secdesc: Failed to marshall security descriptor\n"));
2365                 result = WERR_NOMEM;
2366                 goto done;
2367         }
2368
2369         result = winreg_printer_write_binary(tmp_ctx,
2370                                              winreg_pipe,
2371                                              &key_hnd,
2372                                              "Security",
2373                                              blob);
2374         if (!W_ERROR_IS_OK(result)) {
2375                 return result;
2376         }
2377
2378         if (psecdesc) {
2379                 *psecdesc = talloc_move(mem_ctx, &secdesc);
2380         }
2381
2382         result = WERR_OK;
2383 done:
2384         if (winreg_pipe != NULL) {
2385                 if (is_valid_policy_hnd(&key_hnd)) {
2386                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2387                 }
2388                 if (is_valid_policy_hnd(&hive_hnd)) {
2389                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2390                 }
2391         }
2392
2393         talloc_free(tmp_ctx);
2394         return result;
2395 }
2396
2397 WERROR winreg_set_printer_secdesc(TALLOC_CTX *mem_ctx,
2398                                   struct auth_serversupplied_info *server_info,
2399                                   const char *sharename,
2400                                   const struct spoolss_security_descriptor *secdesc)
2401 {
2402         const struct spoolss_security_descriptor *new_secdesc = secdesc;
2403         struct spoolss_security_descriptor *old_secdesc;
2404         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2405         struct rpc_pipe_client *winreg_pipe = NULL;
2406         struct policy_handle hive_hnd, key_hnd;
2407         enum ndr_err_code ndr_err;
2408         const char *path;
2409         DATA_BLOB blob;
2410         TALLOC_CTX *tmp_ctx;
2411         WERROR result;
2412
2413         tmp_ctx = talloc_stackframe();
2414         if (tmp_ctx == NULL) {
2415                 return WERR_NOMEM;
2416         }
2417
2418         path = winreg_printer_data_keyname(tmp_ctx, sharename);
2419         if (path == NULL) {
2420                 talloc_free(tmp_ctx);
2421                 return WERR_NOMEM;
2422         }
2423
2424         /*
2425          * The old owner and group sids of the security descriptor are not
2426          * present when new ACEs are added or removed by changing printer
2427          * permissions through NT.  If they are NULL in the new security
2428          * descriptor then copy them over from the old one.
2429          */
2430         if (!secdesc->owner_sid || !secdesc->group_sid) {
2431                 struct dom_sid *owner_sid, *group_sid;
2432                 struct security_acl *dacl, *sacl;
2433                 size_t size;
2434
2435                 result = winreg_get_printer_secdesc(tmp_ctx,
2436                                                     server_info,
2437                                                     sharename,
2438                                                     &old_secdesc);
2439                 if (!W_ERROR_IS_OK(result)) {
2440                         talloc_free(tmp_ctx);
2441                         return result;
2442                 }
2443
2444                 /* Pick out correct owner and group sids */
2445                 owner_sid = secdesc->owner_sid ?
2446                             secdesc->owner_sid :
2447                             old_secdesc->owner_sid;
2448
2449                 group_sid = secdesc->group_sid ?
2450                             secdesc->group_sid :
2451                             old_secdesc->group_sid;
2452
2453                 dacl = secdesc->dacl ?
2454                        secdesc->dacl :
2455                        old_secdesc->dacl;
2456
2457                 sacl = secdesc->sacl ?
2458                        secdesc->sacl :
2459                        old_secdesc->sacl;
2460
2461                 /* Make a deep copy of the security descriptor */
2462                 new_secdesc = make_sec_desc(tmp_ctx,
2463                                             secdesc->revision,
2464                                             secdesc->type,
2465                                             owner_sid,
2466                                             group_sid,
2467                                             sacl,
2468                                             dacl,
2469                                             &size);
2470                 if (new_secdesc == NULL) {
2471                         talloc_free(tmp_ctx);
2472                         return WERR_NOMEM;
2473                 }
2474         }
2475
2476         ZERO_STRUCT(hive_hnd);
2477         ZERO_STRUCT(key_hnd);
2478
2479         result = winreg_printer_openkey(tmp_ctx,
2480                                         server_info,
2481                                         &winreg_pipe,
2482                                         path,
2483                                         "",
2484                                         false,
2485                                         access_mask,
2486                                         &hive_hnd,
2487                                         &key_hnd);
2488         if (!W_ERROR_IS_OK(result)) {
2489                 goto done;
2490         }
2491
2492         ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, new_secdesc,
2493                         (ndr_push_flags_fn_t) ndr_push_security_descriptor);
2494         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2495                 DEBUG(0, ("winreg_set_secdesc: Failed to marshall security descriptor\n"));
2496                 result = WERR_NOMEM;
2497                 goto done;
2498         }
2499
2500         result = winreg_printer_write_binary(tmp_ctx,
2501                                              winreg_pipe,
2502                                              &key_hnd,
2503                                              "Security",
2504                                              blob);
2505
2506 done:
2507         if (winreg_pipe != NULL) {
2508                 if (is_valid_policy_hnd(&key_hnd)) {
2509                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2510                 }
2511                 if (is_valid_policy_hnd(&hive_hnd)) {
2512                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2513                 }
2514         }
2515
2516         talloc_free(tmp_ctx);
2517         return result;
2518 }
2519
2520 /* Set printer data over the winreg pipe. */
2521 WERROR winreg_set_printer_dataex(TALLOC_CTX *mem_ctx,
2522                                  struct auth_serversupplied_info *server_info,
2523                                  const char *printer,
2524                                  const char *key,
2525                                  const char *value,
2526                                  enum winreg_Type type,
2527                                  uint8_t *data,
2528                                  uint32_t data_size)
2529 {
2530         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2531         struct rpc_pipe_client *winreg_pipe = NULL;
2532         struct policy_handle hive_hnd, key_hnd;
2533         struct winreg_String wvalue;
2534         char *path;
2535         WERROR result = WERR_OK;
2536         NTSTATUS status;
2537         TALLOC_CTX *tmp_ctx;
2538
2539         tmp_ctx = talloc_stackframe();
2540         if (tmp_ctx == NULL) {
2541                 return WERR_NOMEM;
2542         }
2543
2544         path = winreg_printer_data_keyname(tmp_ctx, printer);
2545         if (path == NULL) {
2546                 TALLOC_FREE(tmp_ctx);
2547                 return WERR_NOMEM;
2548         }
2549
2550         ZERO_STRUCT(hive_hnd);
2551         ZERO_STRUCT(key_hnd);
2552
2553         DEBUG(8, ("winreg_set_printer_dataex: Open printer key %s, value %s, access_mask: 0x%05x for [%s]\n",
2554                         key, value, access_mask, printer));
2555         result = winreg_printer_openkey(tmp_ctx,
2556                                         server_info,
2557                                         &winreg_pipe,
2558                                         path,
2559                                         key,
2560                                         true,
2561                                         access_mask,
2562                                         &hive_hnd,
2563                                         &key_hnd);
2564         if (!W_ERROR_IS_OK(result)) {
2565                 DEBUG(0, ("winreg_set_printer_dataex: Could not open key %s: %s\n",
2566                           key, win_errstr(result)));
2567                 goto done;
2568         }
2569
2570         wvalue.name = value;
2571         status = rpccli_winreg_SetValue(winreg_pipe,
2572                                         tmp_ctx,
2573                                         &key_hnd,
2574                                         wvalue,
2575                                         type,
2576                                         data,
2577                                         data_size,
2578                                         &result);
2579         if (!NT_STATUS_IS_OK(status)) {
2580                 DEBUG(0, ("winreg_set_printer_dataex: Could not set value %s: %s\n",
2581                           value, nt_errstr(status)));
2582                 if (!W_ERROR_IS_OK(result)) {
2583                         goto done;
2584                 }
2585                 result = ntstatus_to_werror(status);
2586                 goto done;
2587         }
2588
2589         result = WERR_OK;
2590 done:
2591         if (winreg_pipe != NULL) {
2592                 if (is_valid_policy_hnd(&key_hnd)) {
2593                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2594                 }
2595                 if (is_valid_policy_hnd(&hive_hnd)) {
2596                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2597                 }
2598         }
2599
2600         TALLOC_FREE(tmp_ctx);
2601         return result;
2602 }
2603
2604 /* Get printer data over a winreg pipe. */
2605 WERROR winreg_get_printer_dataex(TALLOC_CTX *mem_ctx,
2606                                  struct auth_serversupplied_info *server_info,
2607                                  const char *printer,
2608                                  const char *key,
2609                                  const char *value,
2610                                  enum winreg_Type *type,
2611                                  uint8_t **data,
2612                                  uint32_t *data_size)
2613 {
2614         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2615         struct rpc_pipe_client *winreg_pipe = NULL;
2616         struct policy_handle hive_hnd, key_hnd;
2617         struct winreg_String wvalue;
2618         enum winreg_Type type_in;
2619         char *path;
2620         uint8_t *data_in;
2621         uint32_t data_in_size = 0;
2622         uint32_t value_len = 0;
2623         WERROR result = WERR_OK;
2624         NTSTATUS status;
2625         TALLOC_CTX *tmp_ctx;
2626
2627         tmp_ctx = talloc_stackframe();
2628         if (tmp_ctx == NULL) {
2629                 return WERR_NOMEM;
2630         }
2631
2632         path = winreg_printer_data_keyname(tmp_ctx, printer);
2633         if (path == NULL) {
2634                 TALLOC_FREE(tmp_ctx);
2635                 return WERR_NOMEM;
2636         }
2637
2638         ZERO_STRUCT(hive_hnd);
2639         ZERO_STRUCT(key_hnd);
2640
2641         result = winreg_printer_openkey(tmp_ctx,
2642                                         server_info,
2643                                         &winreg_pipe,
2644                                         path,
2645                                         key,
2646                                         false,
2647                                         access_mask,
2648                                         &hive_hnd,
2649                                         &key_hnd);
2650         if (!W_ERROR_IS_OK(result)) {
2651                 DEBUG(2, ("winreg_get_printer_dataex: Could not open key %s: %s\n",
2652                           key, win_errstr(result)));
2653                 goto done;
2654         }
2655
2656         wvalue.name = value;
2657
2658         /*
2659          * call QueryValue once with data == NULL to get the
2660          * needed memory size to be allocated, then allocate
2661          * data buffer and call again.
2662          */
2663         status = rpccli_winreg_QueryValue(winreg_pipe,
2664                                           tmp_ctx,
2665                                           &key_hnd,
2666                                           &wvalue,
2667                                           &type_in,
2668                                           NULL,
2669                                           &data_in_size,
2670                                           &value_len,
2671                                           &result);
2672         if (!NT_STATUS_IS_OK(status)) {
2673                 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2674                           value, nt_errstr(status)));
2675                 if (!W_ERROR_IS_OK(result)) {
2676                         goto done;
2677                 }
2678                 result = ntstatus_to_werror(status);
2679                 goto done;
2680         }
2681
2682         data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
2683         if (data_in == NULL) {
2684                 result = WERR_NOMEM;
2685                 goto done;
2686         }
2687         value_len = 0;
2688
2689         status = rpccli_winreg_QueryValue(winreg_pipe,
2690                                           tmp_ctx,
2691                                           &key_hnd,
2692                                           &wvalue,
2693                                           &type_in,
2694                                           data_in,
2695                                           &data_in_size,
2696                                           &value_len,
2697                                           &result);
2698         if (!NT_STATUS_IS_OK(status)) {
2699                 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2700                           value, nt_errstr(status)));
2701                 if (!W_ERROR_IS_OK(result)) {
2702                         result = ntstatus_to_werror(status);
2703                 }
2704                 goto done;
2705         }
2706
2707         *type = type_in;
2708         *data_size = data_in_size;
2709         if (data_in_size) {
2710                 *data = talloc_move(mem_ctx, &data_in);
2711         }
2712
2713         result = WERR_OK;
2714 done:
2715         if (winreg_pipe != NULL) {
2716                 if (is_valid_policy_hnd(&key_hnd)) {
2717                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2718                 }
2719                 if (is_valid_policy_hnd(&hive_hnd)) {
2720                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2721                 }
2722         }
2723
2724         TALLOC_FREE(tmp_ctx);
2725         return result;
2726 }
2727
2728 /* Enumerate on the values of a given key and provide the data. */
2729 WERROR winreg_enum_printer_dataex(TALLOC_CTX *mem_ctx,
2730                                   struct auth_serversupplied_info *server_info,
2731                                   const char *printer,
2732                                   const char *key,
2733                                   uint32_t *pnum_values,
2734                                   struct spoolss_PrinterEnumValues **penum_values)
2735 {
2736         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2737         struct rpc_pipe_client *winreg_pipe = NULL;
2738         struct policy_handle hive_hnd, key_hnd;
2739
2740         struct spoolss_PrinterEnumValues *enum_values = NULL;
2741         uint32_t num_values = 0;
2742         char *path;
2743         WERROR result = WERR_OK;
2744
2745         TALLOC_CTX *tmp_ctx;
2746
2747         tmp_ctx = talloc_stackframe();
2748         if (tmp_ctx == NULL) {
2749                 return WERR_NOMEM;
2750         }
2751
2752         path = winreg_printer_data_keyname(tmp_ctx, printer);
2753         if (path == NULL) {
2754                 TALLOC_FREE(tmp_ctx);
2755                 return WERR_NOMEM;
2756         }
2757
2758         result = winreg_printer_openkey(tmp_ctx,
2759                                         server_info,
2760                                         &winreg_pipe,
2761                                         path,
2762                                         key,
2763                                         false,
2764                                         access_mask,
2765                                         &hive_hnd,
2766                                         &key_hnd);
2767         if (!W_ERROR_IS_OK(result)) {
2768                 DEBUG(2, ("winreg_enum_printer_dataex: Could not open key %s: %s\n",
2769                           key, win_errstr(result)));
2770                 goto done;
2771         }
2772
2773         result = winreg_printer_enumvalues(tmp_ctx,
2774                                            winreg_pipe,
2775                                            &key_hnd,
2776                                            &num_values,
2777                                            &enum_values);
2778         if (!W_ERROR_IS_OK(result)) {
2779                 DEBUG(0, ("winreg_enum_printer_dataex: Could not enumerate values in %s: %s\n",
2780                           key, win_errstr(result)));
2781                 goto done;
2782         }
2783
2784         *pnum_values = num_values;
2785         if (penum_values) {
2786                 *penum_values = talloc_move(mem_ctx, &enum_values);
2787         }
2788
2789         result = WERR_OK;
2790 done:
2791         if (winreg_pipe != NULL) {
2792                 if (is_valid_policy_hnd(&key_hnd)) {
2793                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2794                 }
2795                 if (is_valid_policy_hnd(&hive_hnd)) {
2796                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2797                 }
2798         }
2799
2800         TALLOC_FREE(tmp_ctx);
2801         return result;
2802 }
2803
2804 /* Delete printer data over a winreg pipe. */
2805 WERROR winreg_delete_printer_dataex(TALLOC_CTX *mem_ctx,
2806                                     struct auth_serversupplied_info *server_info,
2807                                     const char *printer,
2808                                     const char *key,
2809                                     const char *value)
2810 {
2811         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2812         struct rpc_pipe_client *winreg_pipe = NULL;
2813         struct policy_handle hive_hnd, key_hnd;
2814         struct winreg_String wvalue;
2815         char *path;
2816         WERROR result = WERR_OK;
2817         NTSTATUS status;
2818
2819         TALLOC_CTX *tmp_ctx;
2820
2821         tmp_ctx = talloc_stackframe();
2822         if (tmp_ctx == NULL) {
2823                 return WERR_NOMEM;
2824         }
2825
2826         path = winreg_printer_data_keyname(tmp_ctx, printer);
2827         if (path == NULL) {
2828                 TALLOC_FREE(tmp_ctx);
2829                 return WERR_NOMEM;
2830         }
2831
2832         ZERO_STRUCT(hive_hnd);
2833         ZERO_STRUCT(key_hnd);
2834
2835         result = winreg_printer_openkey(tmp_ctx,
2836                                         server_info,
2837                                         &winreg_pipe,
2838                                         path,
2839                                         key,
2840                                         false,
2841                                         access_mask,
2842                                         &hive_hnd,
2843                                         &key_hnd);
2844         if (!W_ERROR_IS_OK(result)) {
2845                 DEBUG(0, ("winreg_delete_printer_dataex: Could not open key %s: %s\n",
2846                           key, win_errstr(result)));
2847                 goto done;
2848         }
2849
2850         wvalue.name = value;
2851         status = rpccli_winreg_DeleteValue(winreg_pipe,
2852                                            tmp_ctx,
2853                                            &key_hnd,
2854                                            wvalue,
2855                                            &result);
2856         if (!NT_STATUS_IS_OK(status)) {
2857                 DEBUG(0, ("winreg_delete_printer_dataex: Could not delete value %s: %s\n",
2858                           value, nt_errstr(status)));
2859                 if (!W_ERROR_IS_OK(result)) {
2860                         goto done;
2861                 }
2862                 result = ntstatus_to_werror(status);
2863                 goto done;
2864         }
2865
2866         result = WERR_OK;
2867 done:
2868         if (winreg_pipe != NULL) {
2869                 if (is_valid_policy_hnd(&key_hnd)) {
2870                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2871                 }
2872                 if (is_valid_policy_hnd(&hive_hnd)) {
2873                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2874                 }
2875         }
2876
2877         TALLOC_FREE(tmp_ctx);
2878         return result;
2879 }
2880
2881 /* Enumerate on the subkeys of a given key and provide the data. */
2882 WERROR winreg_enum_printer_key(TALLOC_CTX *mem_ctx,
2883                                struct auth_serversupplied_info *server_info,
2884                                const char *printer,
2885                                const char *key,
2886                                uint32_t *pnum_subkeys,
2887                                const char ***psubkeys)
2888 {
2889         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2890         struct rpc_pipe_client *winreg_pipe = NULL;
2891         struct policy_handle hive_hnd, key_hnd;
2892         char *path;
2893         const char **subkeys = NULL;
2894         uint32_t num_subkeys = -1;
2895
2896         WERROR result = WERR_OK;
2897
2898         TALLOC_CTX *tmp_ctx;
2899
2900         tmp_ctx = talloc_stackframe();
2901         if (tmp_ctx == NULL) {
2902                 return WERR_NOMEM;
2903         }
2904
2905         path = winreg_printer_data_keyname(tmp_ctx, printer);
2906         if (path == NULL) {
2907                 TALLOC_FREE(tmp_ctx);
2908                 return WERR_NOMEM;
2909         }
2910
2911         ZERO_STRUCT(hive_hnd);
2912         ZERO_STRUCT(key_hnd);
2913
2914         result = winreg_printer_openkey(tmp_ctx,
2915                                         server_info,
2916                                         &winreg_pipe,
2917                                         path,
2918                                         key,
2919                                         false,
2920                                         access_mask,
2921                                         &hive_hnd,
2922                                         &key_hnd);
2923         if (!W_ERROR_IS_OK(result)) {
2924                 DEBUG(2, ("winreg_enum_printer_key: Could not open key %s: %s\n",
2925                           key, win_errstr(result)));
2926                 goto done;
2927         }
2928
2929         result = winreg_printer_enumkeys(tmp_ctx,
2930                                          winreg_pipe,
2931                                          &key_hnd,
2932                                          &num_subkeys,
2933                                          &subkeys);
2934         if (!W_ERROR_IS_OK(result)) {
2935                 DEBUG(0, ("winreg_enum_printer_key: Could not enumerate subkeys in %s: %s\n",
2936                           key, win_errstr(result)));
2937                 goto done;
2938         }
2939
2940         *pnum_subkeys = num_subkeys;
2941         if (psubkeys) {
2942                 *psubkeys = talloc_move(mem_ctx, &subkeys);
2943         }
2944
2945         result = WERR_OK;
2946 done:
2947         if (winreg_pipe != NULL) {
2948                 if (is_valid_policy_hnd(&key_hnd)) {
2949                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2950                 }
2951                 if (is_valid_policy_hnd(&hive_hnd)) {
2952                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2953                 }
2954         }
2955
2956         TALLOC_FREE(tmp_ctx);
2957         return result;
2958 }
2959
2960 /* Delete a key with subkeys of a given printer. */
2961 WERROR winreg_delete_printer_key(TALLOC_CTX *mem_ctx,
2962                                  struct auth_serversupplied_info *server_info,
2963                                  const char *printer,
2964                                  const char *key)
2965 {
2966         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2967         struct rpc_pipe_client *winreg_pipe = NULL;
2968         struct policy_handle hive_hnd, key_hnd;
2969         char *keyname;
2970         char *path;
2971         WERROR result;
2972         TALLOC_CTX *tmp_ctx;
2973
2974         tmp_ctx = talloc_stackframe();
2975         if (tmp_ctx == NULL) {
2976                 return WERR_NOMEM;
2977         }
2978
2979         path = winreg_printer_data_keyname(tmp_ctx, printer);
2980         if (path == NULL) {
2981                 TALLOC_FREE(tmp_ctx);
2982                 return WERR_NOMEM;
2983         }
2984