s3-spoolss: Fixed a possible segfault in winreg_get_printer.
[samba.git] / source3 / rpc_server / srv_spoolss_util.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *
4  *  SPOOLSS RPC Pipe server / winreg client routines
5  *
6  *  Copyright (c) 2010      Andreas Schneider <asn@samba.org>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "nt_printing.h"
24 #include "srv_spoolss_util.h"
25 #include "../librpc/gen_ndr/ndr_spoolss.h"
26 #include "../librpc/gen_ndr/srv_winreg.h"
27 #include "../librpc/gen_ndr/cli_winreg.h"
28 #include "../librpc/gen_ndr/ndr_security.h"
29
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_new(mem_ctx);
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 = NULL;
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 = (uint8_t *) TALLOC(tmp_ctx, data_size);
457                 length = 0;
458
459                 status = rpccli_winreg_EnumValue(pipe_handle,
460                                                  tmp_ctx,
461                                                  key_hnd,
462                                                  i,
463                                                  &name_buf,
464                                                  &type,
465                                                  data,
466                                                  &data_size,
467                                                  &length,
468                                                  &result);
469                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
470                         result = WERR_OK;
471                         status = NT_STATUS_OK;
472                         break;
473                 }
474
475                 if (!NT_STATUS_IS_OK(status)) {
476                         DEBUG(0, ("winreg_printer_enumvalues: Could not enumerate values: %s\n",
477                                   nt_errstr(status)));
478                         if (!W_ERROR_IS_OK(result)) {
479                                 goto error;
480                         }
481                         result = ntstatus_to_werror(status);
482                         goto error;
483                 }
484
485                 if (name_buf.name == NULL) {
486                         result = WERR_INVALID_PARAMETER;
487                         goto error;
488                 }
489
490                 val.value_name = talloc_strdup(enum_values, name_buf.name);
491                 if (val.value_name == NULL) {
492                         result = WERR_NOMEM;
493                         goto error;
494                 }
495                 val.value_name_len = strlen_m_term(val.value_name) * 2;
496
497                 val.type = type;
498                 val.data_length = data_size;
499                 val.data = NULL;
500                 if (val.data_length) {
501                         val.data = talloc(enum_values, DATA_BLOB);
502                         if (val.data == NULL) {
503                                 result = WERR_NOMEM;
504                                 goto error;
505                         }
506                         *val.data = data_blob_talloc(enum_values, data, data_size);
507                 }
508
509                 enum_values[i] = val;
510         }
511
512         *pnum_values = num_values;
513         if (penum_values) {
514                 *penum_values = talloc_move(mem_ctx, &enum_values);
515         }
516
517         result = WERR_OK;
518
519  error:
520         TALLOC_FREE(tmp_ctx);
521         return result;
522 }
523
524 /**
525  * @internal
526  *
527  * @brief Enumerate subkeys of an opened key handle and get the names.
528  *
529  * @param[in]  mem_ctx  The memory context to use.
530  *
531  * @param[in]  pipe_handle The pipe handle for the rpc connection.
532  *
533  * @param[in]  key_hnd  The opened key handle.
534  *
535  * @param[in]  pnum_subkeys A pointer to store the number of found subkeys.
536  *
537  * @param[in]  psubkeys A pointer to an array to store the found names of
538  *                      subkeys.
539  *
540  * @return                   WERR_OK on success, the corresponding DOS error
541  *                           code if something gone wrong.
542  */
543 static WERROR winreg_printer_enumkeys(TALLOC_CTX *mem_ctx,
544                                       struct rpc_pipe_client *pipe_handle,
545                                       struct policy_handle *key_hnd,
546                                       uint32_t *pnum_subkeys,
547                                       const char ***psubkeys)
548 {
549         TALLOC_CTX *tmp_ctx;
550         const char **subkeys;
551         uint32_t num_subkeys, max_subkeylen, max_classlen;
552         uint32_t num_values, max_valnamelen, max_valbufsize;
553         uint32_t i;
554         NTTIME last_changed_time;
555         uint32_t secdescsize;
556         struct winreg_String classname;
557         WERROR result = WERR_OK;
558         NTSTATUS status;
559
560         tmp_ctx = talloc_new(mem_ctx);
561         if (tmp_ctx == NULL) {
562                 return WERR_NOMEM;
563         }
564
565         ZERO_STRUCT(classname);
566
567         status = rpccli_winreg_QueryInfoKey(pipe_handle,
568                                             tmp_ctx,
569                                             key_hnd,
570                                             &classname,
571                                             &num_subkeys,
572                                             &max_subkeylen,
573                                             &max_classlen,
574                                             &num_values,
575                                             &max_valnamelen,
576                                             &max_valbufsize,
577                                             &secdescsize,
578                                             &last_changed_time,
579                                             &result);
580         if (!NT_STATUS_IS_OK(status)) {
581                 DEBUG(0, ("winreg_printer_enumkeys: Could not query info: %s\n",
582                           nt_errstr(status)));
583                 if (!W_ERROR_IS_OK(result)) {
584                         goto error;
585                 }
586                 result = ntstatus_to_werror(status);
587                 goto error;
588         }
589
590         subkeys = talloc_zero_array(tmp_ctx, const char *, num_subkeys + 2);
591         if (subkeys == NULL) {
592                 result = WERR_NOMEM;
593                 goto error;
594         }
595
596         if (num_subkeys == 0) {
597                 subkeys[0] = talloc_strdup(subkeys, "");
598                 if (subkeys[0] == NULL) {
599                         result = WERR_NOMEM;
600                         goto error;
601                 }
602                 *pnum_subkeys = 0;
603                 if (psubkeys) {
604                         *psubkeys = talloc_move(mem_ctx, &subkeys);
605                 }
606
607                 TALLOC_FREE(tmp_ctx);
608                 return WERR_OK;
609         }
610
611         for (i = 0; i < num_subkeys; i++) {
612                 char c = '\0';
613                 char n = '\0';
614                 char *name = NULL;
615                 struct winreg_StringBuf class_buf;
616                 struct winreg_StringBuf name_buf;
617                 NTTIME modtime;
618
619                 class_buf.name = &c;
620                 class_buf.size = max_classlen + 2;
621                 class_buf.length = 0;
622
623                 name_buf.name = &n;
624                 name_buf.size = max_subkeylen + 2;
625                 name_buf.length = 0;
626
627                 ZERO_STRUCT(modtime);
628
629                 status = rpccli_winreg_EnumKey(pipe_handle,
630                                                tmp_ctx,
631                                                key_hnd,
632                                                i,
633                                                &name_buf,
634                                                &class_buf,
635                                                &modtime,
636                                                &result);
637                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
638                         result = WERR_OK;
639                         status = NT_STATUS_OK;
640                         break;
641                 }
642
643                 if (!NT_STATUS_IS_OK(status)) {
644                         DEBUG(0, ("winreg_printer_enumkeys: Could not enumerate keys: %s\n",
645                                   nt_errstr(status)));
646                         if (!W_ERROR_IS_OK(result)) {
647                                 goto error;
648                         }
649                         result = ntstatus_to_werror(status);
650                         goto error;
651                 }
652
653                 if (name_buf.name == NULL) {
654                         result = WERR_INVALID_PARAMETER;
655                         goto error;
656                 }
657
658                 name = talloc_strdup(subkeys, name_buf.name);
659                 if (name == NULL) {
660                         result = WERR_NOMEM;
661                         goto error;
662                 }
663
664                 subkeys[i] = name;
665         }
666
667         *pnum_subkeys = num_subkeys;
668         if (psubkeys) {
669                 *psubkeys = talloc_move(mem_ctx, &subkeys);
670         }
671
672  error:
673         TALLOC_FREE(tmp_ctx);
674         return result;
675 }
676
677 /**
678  * @internal
679  *
680  * @brief A function to delete a key and its subkeys recurively.
681  *
682  * @param[in]  mem_ctx  The memory context to use.
683  *
684  * @param[in]  pipe_handle The pipe handle for the rpc connection.
685  *
686  * @param[in]  hive_handle A opened hive handle to the key.
687  *
688  * @param[in]  access_mask The access mask to access the key.
689  *
690  * @param[in]  key      The key to delete
691  *
692  * @return              WERR_OK on success, the corresponding DOS error
693  *                      code if something gone wrong.
694  */
695 static WERROR winreg_printer_delete_subkeys(TALLOC_CTX *mem_ctx,
696                                             struct rpc_pipe_client *pipe_handle,
697                                             struct policy_handle *hive_handle,
698                                             uint32_t access_mask,
699                                             const char *key)
700 {
701         const char **subkeys = NULL;
702         uint32_t num_subkeys = 0;
703         struct policy_handle key_hnd;
704         struct winreg_String wkey;
705         WERROR result = WERR_OK;
706         NTSTATUS status;
707         uint32_t i;
708
709         ZERO_STRUCT(key_hnd);
710         wkey.name = key;
711
712         DEBUG(2, ("winreg_printer_delete_subkeys: delete key %s\n", key));
713         /* open the key */
714         status = rpccli_winreg_OpenKey(pipe_handle,
715                                        mem_ctx,
716                                        hive_handle,
717                                        wkey,
718                                        0,
719                                        access_mask,
720                                        &key_hnd,
721                                        &result);
722         if (!NT_STATUS_IS_OK(status)) {
723                 DEBUG(0, ("winreg_printer_delete_subkeys: Could not open key %s: %s\n",
724                           wkey.name, nt_errstr(status)));
725                 if (!W_ERROR_IS_OK(result)) {
726                         return result;
727                 }
728                 return ntstatus_to_werror(status);
729         }
730
731         result = winreg_printer_enumkeys(mem_ctx,
732                                          pipe_handle,
733                                          &key_hnd,
734                                          &num_subkeys,
735                                          &subkeys);
736         if (!W_ERROR_IS_OK(result)) {
737                 goto done;
738         }
739
740         for (i = 0; i < num_subkeys; i++) {
741                 /* create key + subkey */
742                 char *subkey = talloc_asprintf(mem_ctx, "%s\\%s", key, subkeys[i]);
743                 if (subkey == NULL) {
744                         goto done;
745                 }
746
747                 DEBUG(2, ("winreg_printer_delete_subkeys: delete subkey %s\n", subkey));
748                 result = winreg_printer_delete_subkeys(mem_ctx,
749                                                        pipe_handle,
750                                                        hive_handle,
751                                                        access_mask,
752                                                        subkey);
753                 if (!W_ERROR_IS_OK(result)) {
754                         goto done;
755                 }
756         }
757
758         if (is_valid_policy_hnd(&key_hnd)) {
759                 rpccli_winreg_CloseKey(pipe_handle, mem_ctx, &key_hnd, NULL);
760         }
761
762         wkey.name = key;
763
764         status = rpccli_winreg_DeleteKey(pipe_handle,
765                                          mem_ctx,
766                                          hive_handle,
767                                          wkey,
768                                          &result);
769
770 done:
771         if (is_valid_policy_hnd(&key_hnd)) {
772                 rpccli_winreg_CloseKey(pipe_handle, mem_ctx, &key_hnd, NULL);
773         }
774
775         return result;
776 }
777
778 static WERROR winreg_printer_write_sz(TALLOC_CTX *mem_ctx,
779                                       struct rpc_pipe_client *pipe_handle,
780                                       struct policy_handle *key_handle,
781                                       const char *value,
782                                       const char *data)
783 {
784         struct winreg_String wvalue;
785         DATA_BLOB blob;
786         WERROR result = WERR_OK;
787         NTSTATUS status;
788
789         wvalue.name = value;
790         if (data == NULL) {
791                 blob = data_blob_string_const("");
792         } else {
793                 if (!push_reg_sz(mem_ctx, &blob, data)) {
794                         DEBUG(0, ("winreg_printer_write_sz: Could not marshall string %s for %s\n",
795                                 data, wvalue.name));
796                         return WERR_NOMEM;
797                 }
798         }
799         status = rpccli_winreg_SetValue(pipe_handle,
800                                         mem_ctx,
801                                         key_handle,
802                                         wvalue,
803                                         REG_SZ,
804                                         blob.data,
805                                         blob.length,
806                                         &result);
807         if (!NT_STATUS_IS_OK(status)) {
808                 DEBUG(0, ("winreg_printer_write_sz: Could not set value %s: %s\n",
809                         wvalue.name, win_errstr(result)));
810                 if (!W_ERROR_IS_OK(result)) {
811                         result = ntstatus_to_werror(status);
812                 }
813         }
814
815         return result;
816 }
817
818 static WERROR winreg_printer_write_dword(TALLOC_CTX *mem_ctx,
819                                          struct rpc_pipe_client *pipe_handle,
820                                          struct policy_handle *key_handle,
821                                          const char *value,
822                                          uint32_t data)
823 {
824         struct winreg_String wvalue;
825         DATA_BLOB blob;
826         WERROR result = WERR_OK;
827         NTSTATUS status;
828
829         wvalue.name = value;
830         blob = data_blob_talloc(mem_ctx, NULL, 4);
831         SIVAL(blob.data, 0, data);
832
833         status = rpccli_winreg_SetValue(pipe_handle,
834                                         mem_ctx,
835                                         key_handle,
836                                         wvalue,
837                                         REG_DWORD,
838                                         blob.data,
839                                         blob.length,
840                                         &result);
841         if (!NT_STATUS_IS_OK(status)) {
842                 DEBUG(0, ("winreg_printer_write_dword: Could not set value %s: %s\n",
843                         wvalue.name, win_errstr(result)));
844                 if (!W_ERROR_IS_OK(result)) {
845                         result = ntstatus_to_werror(status);
846                 }
847         }
848
849         return result;
850 }
851
852 static WERROR winreg_printer_write_binary(TALLOC_CTX *mem_ctx,
853                                           struct rpc_pipe_client *pipe_handle,
854                                           struct policy_handle *key_handle,
855                                           const char *value,
856                                           DATA_BLOB blob)
857 {
858         struct winreg_String wvalue;
859         WERROR result = WERR_OK;
860         NTSTATUS status;
861
862         wvalue.name = value;
863         status = rpccli_winreg_SetValue(pipe_handle,
864                                         mem_ctx,
865                                         key_handle,
866                                         wvalue,
867                                         REG_BINARY,
868                                         blob.data,
869                                         blob.length,
870                                         &result);
871         if (!NT_STATUS_IS_OK(status)) {
872                 DEBUG(0, ("winreg_printer_write_binary: Could not set value %s: %s\n",
873                         wvalue.name, win_errstr(result)));
874                 if (!W_ERROR_IS_OK(result)) {
875                         result = ntstatus_to_werror(status);
876                 }
877         }
878
879         return result;
880 }
881
882 static WERROR winreg_printer_query_binary(TALLOC_CTX *mem_ctx,
883                                           struct rpc_pipe_client *pipe_handle,
884                                           struct policy_handle *key_handle,
885                                           const char *value,
886                                           DATA_BLOB *data)
887 {
888         struct winreg_String wvalue;
889         enum winreg_Type type;
890         WERROR result = WERR_OK;
891         uint32_t value_len = 0;
892         uint32_t data_size = 0;
893         NTSTATUS status;
894         DATA_BLOB blob;
895
896         wvalue.name = value;
897         status = rpccli_winreg_QueryValue(pipe_handle,
898                                           mem_ctx,
899                                           key_handle,
900                                           &wvalue,
901                                           &type,
902                                           NULL,
903                                           &data_size,
904                                           &value_len,
905                                           &result);
906         if (!NT_STATUS_IS_OK(status)) {
907                 DEBUG(0, ("winreg_printer_query_dword: Could not query value %s: %s\n",
908                           wvalue.name, nt_errstr(status)));
909                 if (!W_ERROR_IS_OK(result)) {
910                         goto done;
911                 }
912                 result = ntstatus_to_werror(status);
913                 goto done;
914         }
915
916         if (type != REG_BINARY) {
917                 result = WERR_INVALID_DATATYPE;
918                 goto done;
919         }
920         blob = data_blob_talloc(mem_ctx, NULL, data_size);
921         if (blob.data == NULL) {
922                 result = WERR_NOMEM;
923                 goto done;
924         }
925         value_len = 0;
926
927         status = rpccli_winreg_QueryValue(pipe_handle,
928                                           mem_ctx,
929                                           key_handle,
930                                           &wvalue,
931                                           &type,
932                                           blob.data,
933                                           &data_size,
934                                           &value_len,
935                                           &result);
936         if (!NT_STATUS_IS_OK(status)) {
937                 DEBUG(0, ("winreg_printer_query_dword: Could not query value %s: %s\n",
938                           wvalue.name, nt_errstr(status)));
939                 if (!W_ERROR_IS_OK(result)) {
940                         result = ntstatus_to_werror(status);
941                 }
942                 goto done;
943         }
944
945         if (data) {
946                 data->data = blob.data;
947                 data->length = blob.length;
948         }
949 done:
950         return result;
951 }
952
953 static WERROR winreg_printer_query_dword(TALLOC_CTX *mem_ctx,
954                                          struct rpc_pipe_client *pipe_handle,
955                                          struct policy_handle *key_handle,
956                                          const char *value,
957                                          uint32_t *data)
958 {
959         struct winreg_String wvalue;
960         enum winreg_Type type;
961         WERROR result = WERR_OK;
962         uint32_t value_len = 0;
963         uint32_t data_size = 0;
964         NTSTATUS status;
965         DATA_BLOB blob;
966
967         wvalue.name = value;
968         status = rpccli_winreg_QueryValue(pipe_handle,
969                                           mem_ctx,
970                                           key_handle,
971                                           &wvalue,
972                                           &type,
973                                           NULL,
974                                           &data_size,
975                                           &value_len,
976                                           &result);
977         if (!NT_STATUS_IS_OK(status)) {
978                 DEBUG(0, ("winreg_printer_query_dword: Could not query value %s: %s\n",
979                           wvalue.name, nt_errstr(status)));
980                 if (!W_ERROR_IS_OK(result)) {
981                         goto done;
982                 }
983                 result = ntstatus_to_werror(status);
984                 goto done;
985         }
986
987         if (type != REG_DWORD) {
988                 result = WERR_INVALID_DATATYPE;
989                 goto done;
990         }
991
992         if (data_size != 4) {
993                 result = WERR_INVALID_DATA;
994                 goto done;
995         }
996
997         blob = data_blob_talloc(mem_ctx, NULL, data_size);
998         if (blob.data == NULL) {
999                 result = WERR_NOMEM;
1000                 goto done;
1001         }
1002         value_len = 0;
1003
1004         status = rpccli_winreg_QueryValue(pipe_handle,
1005                                           mem_ctx,
1006                                           key_handle,
1007                                           &wvalue,
1008                                           &type,
1009                                           blob.data,
1010                                           &data_size,
1011                                           &value_len,
1012                                           &result);
1013         if (!NT_STATUS_IS_OK(status)) {
1014                 DEBUG(0, ("winreg_printer_query_dword: Could not query value %s: %s\n",
1015                           wvalue.name, nt_errstr(status)));
1016                 if (!W_ERROR_IS_OK(result)) {
1017                         result = ntstatus_to_werror(status);
1018                 }
1019                 goto done;
1020         }
1021
1022         if (data) {
1023                 *data = IVAL(blob.data, 0);
1024         }
1025 done:
1026         return result;
1027 }
1028
1029 static WERROR winreg_printer_write_multi_sz(TALLOC_CTX *mem_ctx,
1030                                             struct rpc_pipe_client *pipe_handle,
1031                                             struct policy_handle *key_handle,
1032                                             const char *value,
1033                                             const char **data)
1034 {
1035         struct winreg_String wvalue;
1036         DATA_BLOB blob;
1037         WERROR result = WERR_OK;
1038         NTSTATUS status;
1039
1040         wvalue.name = value;
1041         if (!push_reg_multi_sz(mem_ctx, &blob, data)) {
1042                 return WERR_NOMEM;
1043         }
1044         status = rpccli_winreg_SetValue(pipe_handle,
1045                                         mem_ctx,
1046                                         key_handle,
1047                                         wvalue,
1048                                         REG_MULTI_SZ,
1049                                         blob.data,
1050                                         blob.length,
1051                                         &result);
1052         if (!NT_STATUS_IS_OK(status)) {
1053                 DEBUG(0, ("winreg_printer_write_multi_sz: Could not set value %s: %s\n",
1054                         wvalue.name, win_errstr(result)));
1055                 if (!W_ERROR_IS_OK(result)) {
1056                         result = ntstatus_to_werror(status);
1057                 }
1058         }
1059
1060         return result;
1061 }
1062
1063 static WERROR winreg_printer_opendriver(TALLOC_CTX *mem_ctx,
1064                                         struct auth_serversupplied_info *server_info,
1065                                         const char *drivername,
1066                                         const char *architecture,
1067                                         uint32_t version,
1068                                         uint32_t access_mask,
1069                                         bool create,
1070                                         struct rpc_pipe_client **winreg_pipe,
1071                                         struct policy_handle *hive_hnd,
1072                                         struct policy_handle *key_hnd)
1073 {
1074         WERROR result;
1075         char *key_name;
1076
1077         key_name = talloc_asprintf(mem_ctx, "%s\\Environments\\%s\\Drivers\\Version-%u",
1078                                    TOP_LEVEL_CONTROL_KEY,
1079                                    architecture, version);
1080         if (!key_name) {
1081                 return WERR_NOMEM;
1082         }
1083
1084         result = winreg_printer_openkey(mem_ctx,
1085                                         server_info,
1086                                         winreg_pipe,
1087                                         key_name,
1088                                         drivername,
1089                                         create,
1090                                         access_mask,
1091                                         hive_hnd,
1092                                         key_hnd);
1093         return result;
1094 }
1095
1096 static WERROR winreg_enumval_to_dword(TALLOC_CTX *mem_ctx,
1097                                       struct spoolss_PrinterEnumValues *v,
1098                                       const char *valuename, uint32_t *dw)
1099 {
1100         /* just return if it is not the one we are looking for */
1101         if (strcmp(valuename, v->value_name) != 0) {
1102                 return WERR_NOT_FOUND;
1103         }
1104
1105         if (v->type != REG_DWORD) {
1106                 return WERR_INVALID_DATATYPE;
1107         }
1108
1109         if (v->data_length == 0) {
1110                 *dw = 0;
1111                 return WERR_OK;
1112         }
1113
1114         *dw = IVAL(v->data->data, 0);
1115         return WERR_OK;
1116 }
1117
1118 static WERROR winreg_enumval_to_sz(TALLOC_CTX *mem_ctx,
1119                                    struct spoolss_PrinterEnumValues *v,
1120                                    const char *valuename, const char **_str)
1121 {
1122         /* just return if it is not the one we are looking for */
1123         if (strcmp(valuename, v->value_name) != 0) {
1124                 return WERR_NOT_FOUND;
1125         }
1126
1127         if (v->type != REG_SZ) {
1128                 return WERR_INVALID_DATATYPE;
1129         }
1130
1131         if (v->data_length == 0) {
1132                 *_str = talloc_strdup(mem_ctx, EMPTY_STRING);
1133                 if (*_str == NULL) {
1134                         return WERR_NOMEM;
1135                 }
1136                 return WERR_OK;
1137         }
1138
1139         if (!pull_reg_sz(mem_ctx, v->data, _str)) {
1140                 return WERR_NOMEM;
1141         }
1142
1143         return WERR_OK;
1144 }
1145
1146 static WERROR winreg_enumval_to_multi_sz(TALLOC_CTX *mem_ctx,
1147                                          struct spoolss_PrinterEnumValues *v,
1148                                          const char *valuename,
1149                                          const char ***array)
1150 {
1151         /* just return if it is not the one we are looking for */
1152         if (strcmp(valuename, v->value_name) != 0) {
1153                 return WERR_NOT_FOUND;
1154         }
1155
1156         if (v->type != REG_MULTI_SZ) {
1157                 return WERR_INVALID_DATATYPE;
1158         }
1159
1160         if (v->data_length == 0) {
1161                 *array = talloc_array(mem_ctx, const char *, 1);
1162                 if (*array == NULL) {
1163                         return WERR_NOMEM;
1164                 }
1165                 *array[0] = NULL;
1166                 return WERR_OK;
1167         }
1168
1169         if (!pull_reg_multi_sz(mem_ctx, v->data, array)) {
1170                 return WERR_NOMEM;
1171         }
1172
1173         return WERR_OK;
1174 }
1175
1176 static WERROR winreg_printer_write_date(TALLOC_CTX *mem_ctx,
1177                                         struct rpc_pipe_client *pipe_handle,
1178                                         struct policy_handle *key_handle,
1179                                         const char *value,
1180                                         NTTIME data)
1181 {
1182         struct winreg_String wvalue;
1183         DATA_BLOB blob;
1184         WERROR result = WERR_OK;
1185         NTSTATUS status;
1186         const char *str;
1187         struct tm *tm;
1188         time_t t;
1189
1190         t = nt_time_to_unix(data);
1191         tm = localtime(&t);
1192         str = talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
1193                               tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
1194         if (!str) {
1195                 return WERR_NOMEM;
1196         }
1197
1198         wvalue.name = value;
1199         if (!push_reg_sz(mem_ctx, &blob, str)) {
1200                 return WERR_NOMEM;
1201         }
1202         status = rpccli_winreg_SetValue(pipe_handle,
1203                                         mem_ctx,
1204                                         key_handle,
1205                                         wvalue,
1206                                         REG_SZ,
1207                                         blob.data,
1208                                         blob.length,
1209                                         &result);
1210         if (!NT_STATUS_IS_OK(status)) {
1211                 DEBUG(0, ("winreg_printer_write_date: Could not set value %s: %s\n",
1212                         wvalue.name, win_errstr(result)));
1213                 if (!W_ERROR_IS_OK(result)) {
1214                         result = ntstatus_to_werror(status);
1215                 }
1216         }
1217
1218         return result;
1219 }
1220
1221 static WERROR winreg_printer_date_to_NTTIME(const char *str, NTTIME *data)
1222 {
1223         struct tm tm;
1224         time_t t;
1225
1226         ZERO_STRUCT(tm);
1227
1228         if (sscanf(str, "%d/%d/%d",
1229                    &tm.tm_mon, &tm.tm_mday, &tm.tm_year) != 3) {
1230                 return WERR_INVALID_PARAMETER;
1231         }
1232         tm.tm_mon -= 1;
1233         tm.tm_year -= 1900;
1234         tm.tm_isdst = -1;
1235
1236         t = mktime(&tm);
1237         unix_to_nt_time(data, t);
1238
1239         return WERR_OK;
1240 }
1241
1242 static WERROR winreg_printer_write_ver(TALLOC_CTX *mem_ctx,
1243                                        struct rpc_pipe_client *pipe_handle,
1244                                        struct policy_handle *key_handle,
1245                                        const char *value,
1246                                        uint64_t data)
1247 {
1248         struct winreg_String wvalue;
1249         DATA_BLOB blob;
1250         WERROR result = WERR_OK;
1251         NTSTATUS status;
1252         char *str;
1253
1254         /* FIXME: check format is right,
1255          *      this needs to be something like: 6.1.7600.16385 */
1256         str = talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
1257                               (unsigned)((data >> 48) & 0xFFFF),
1258                               (unsigned)((data >> 32) & 0xFFFF),
1259                               (unsigned)((data >> 16) & 0xFFFF),
1260                               (unsigned)(data & 0xFFFF));
1261         if (!str) {
1262                 return WERR_NOMEM;
1263         }
1264
1265         wvalue.name = value;
1266         if (!push_reg_sz(mem_ctx, &blob, str)) {
1267                 return WERR_NOMEM;
1268         }
1269         status = rpccli_winreg_SetValue(pipe_handle,
1270                                         mem_ctx,
1271                                         key_handle,
1272                                         wvalue,
1273                                         REG_SZ,
1274                                         blob.data,
1275                                         blob.length,
1276                                         &result);
1277         if (!NT_STATUS_IS_OK(status)) {
1278                 DEBUG(0, ("winreg_printer_write_date: Could not set value %s: %s\n",
1279                         wvalue.name, win_errstr(result)));
1280                 if (!W_ERROR_IS_OK(result)) {
1281                         result = ntstatus_to_werror(status);
1282                 }
1283         }
1284
1285         return result;
1286 }
1287
1288 static WERROR winreg_printer_ver_to_dword(const char *str, uint64_t *data)
1289 {
1290         unsigned int v1, v2, v3, v4;
1291
1292         if (sscanf(str, "%u.%u.%u.%u", &v1, &v2, &v3, &v4) != 4) {
1293                 return WERR_INVALID_PARAMETER;
1294         }
1295
1296         *data = ((uint64_t)(v1 & 0xFFFF) << 48) +
1297                 ((uint64_t)(v2 & 0xFFFF) << 32) +
1298                 ((uint64_t)(v3 & 0xFFFF) << 16) +
1299                 (uint64_t)(v2 & 0xFFFF);
1300
1301         return WERR_OK;
1302 }
1303
1304 /********************************************************************
1305  Public winreg function for spoolss
1306 ********************************************************************/
1307
1308 WERROR winreg_create_printer(TALLOC_CTX *mem_ctx,
1309                              struct auth_serversupplied_info *server_info,
1310                              const char *servername,
1311                              const char *sharename)
1312 {
1313         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1314         struct rpc_pipe_client *winreg_pipe = NULL;
1315         struct policy_handle hive_hnd, key_hnd;
1316         struct spoolss_SetPrinterInfo2 *info2;
1317         struct security_descriptor *secdesc;
1318         struct winreg_String wkey, wkeyclass;
1319         const char *path;
1320         const char *subkeys[] = { SPOOL_DSDRIVER_KEY, SPOOL_DSSPOOLER_KEY, SPOOL_PRINTERDATA_KEY };
1321         uint32_t i, count = ARRAY_SIZE(subkeys);
1322         uint32_t info2_mask = 0;
1323         WERROR result = WERR_OK;
1324         TALLOC_CTX *tmp_ctx;
1325
1326         tmp_ctx = talloc_new(mem_ctx);
1327         if (tmp_ctx == NULL) {
1328                 return WERR_NOMEM;
1329         }
1330
1331         path = winreg_printer_data_keyname(tmp_ctx, sharename);
1332         if (path == NULL) {
1333                 TALLOC_FREE(tmp_ctx);
1334                 return WERR_NOMEM;
1335         }
1336
1337         ZERO_STRUCT(hive_hnd);
1338         ZERO_STRUCT(key_hnd);
1339
1340         result = winreg_printer_openkey(tmp_ctx,
1341                                         server_info,
1342                                         &winreg_pipe,
1343                                         path,
1344                                         "",
1345                                         false,
1346                                         access_mask,
1347                                         &hive_hnd,
1348                                         &key_hnd);
1349         if (W_ERROR_IS_OK(result)) {
1350                 DEBUG(2, ("winreg_create_printer: Skipping, %s already exists\n", path));
1351                 goto done;
1352         } else if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1353                 DEBUG(2, ("winreg_create_printer: Creating default values in %s\n", path));
1354         } else if (!W_ERROR_IS_OK(result)) {
1355                 DEBUG(0, ("winreg_create_printer: Could not open key %s: %s\n",
1356                         path, win_errstr(result)));
1357                 goto done;
1358         }
1359
1360         /* Create the main key */
1361         result = winreg_printer_openkey(tmp_ctx,
1362                                         server_info,
1363                                         &winreg_pipe,
1364                                         path,
1365                                         "",
1366                                         true,
1367                                         access_mask,
1368                                         &hive_hnd,
1369                                         &key_hnd);
1370         if (!W_ERROR_IS_OK(result)) {
1371                 DEBUG(0, ("winreg_create_printer_keys: Could not create key %s: %s\n",
1372                         path, win_errstr(result)));
1373                 goto done;
1374         }
1375
1376         if (is_valid_policy_hnd(&key_hnd)) {
1377                 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1378         }
1379
1380         /* Create subkeys */
1381         for (i = 0; i < count; i++) {
1382                 NTSTATUS status;
1383                 enum winreg_CreateAction action = REG_ACTION_NONE;
1384
1385                 ZERO_STRUCT(key_hnd);
1386                 ZERO_STRUCT(wkey);
1387
1388                 wkey.name = talloc_asprintf(tmp_ctx, "%s\\%s", path, subkeys[i]);
1389                 if (wkey.name == NULL) {
1390                         result = WERR_NOMEM;
1391                         goto done;
1392                 }
1393
1394                 ZERO_STRUCT(wkeyclass);
1395                 wkeyclass.name = "";
1396
1397                 status = rpccli_winreg_CreateKey(winreg_pipe,
1398                                                  tmp_ctx,
1399                                                  &hive_hnd,
1400                                                  wkey,
1401                                                  wkeyclass,
1402                                                  0,
1403                                                  access_mask,
1404                                                  NULL,
1405                                                  &key_hnd,
1406                                                  &action,
1407                                                  &result);
1408                 if (!NT_STATUS_IS_OK(status)) {
1409                         DEBUG(0, ("winreg_create_printer_keys: Could not create key %s: %s\n",
1410                                 wkey.name, win_errstr(result)));
1411                         if (!W_ERROR_IS_OK(result)) {
1412                                 result = ntstatus_to_werror(status);
1413                         }
1414                         goto done;
1415                 }
1416
1417                 switch (i) {
1418                 case 1: {
1419                         const char *dnssuffix;
1420                         const char *longname;
1421                         const char *uncname;
1422
1423                         result = winreg_printer_write_sz(tmp_ctx,
1424                                                          winreg_pipe,
1425                                                          &key_hnd,
1426                                                          SPOOL_REG_PRINTERNAME,
1427                                                          sharename);
1428                         if (!W_ERROR_IS_OK(result)) {
1429                                 goto done;
1430                         }
1431
1432                         result = winreg_printer_write_sz(tmp_ctx,
1433                                                          winreg_pipe,
1434                                                          &key_hnd,
1435                                                          SPOOL_REG_SHORTSERVERNAME,
1436                                                          global_myname());
1437                         if (!W_ERROR_IS_OK(result)) {
1438                                 goto done;
1439                         }
1440
1441                         /* We make the assumption that the netbios name
1442                          * is the same as the DNS name since the former
1443                          * will be what we used to join the domain
1444                          */
1445                         dnssuffix = get_mydnsdomname(tmp_ctx);
1446                         if (dnssuffix != NULL && dnssuffix[0] != '\0') {
1447                                 longname = talloc_asprintf(tmp_ctx, "%s.%s", global_myname(), dnssuffix);
1448                         } else {
1449                                 longname = talloc_strdup(tmp_ctx, global_myname());
1450                         }
1451                         if (longname == NULL) {
1452                                 result = WERR_NOMEM;
1453                                 goto done;
1454                         }
1455
1456                         result = winreg_printer_write_sz(tmp_ctx,
1457                                                          winreg_pipe,
1458                                                          &key_hnd,
1459                                                          SPOOL_REG_SERVERNAME,
1460                                                          longname);
1461                         if (!W_ERROR_IS_OK(result)) {
1462                                 goto done;
1463                         }
1464
1465                         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
1466                                                   longname, sharename);
1467                         if (uncname == NULL) {
1468                                 result = WERR_NOMEM;
1469                                 goto done;
1470                         }
1471
1472                         result = winreg_printer_write_sz(tmp_ctx,
1473                                                          winreg_pipe,
1474                                                          &key_hnd,
1475                                                          SPOOL_REG_UNCNAME,
1476                                                          uncname);
1477                         if (!W_ERROR_IS_OK(result)) {
1478                                 goto done;
1479                         }
1480
1481                         result = winreg_printer_write_dword(tmp_ctx,
1482                                                             winreg_pipe,
1483                                                             &key_hnd,
1484                                                             SPOOL_REG_VERSIONNUMBER,
1485                                                             4);
1486                         if (!W_ERROR_IS_OK(result)) {
1487                                 goto done;
1488                         }
1489
1490                         result = winreg_printer_write_dword(tmp_ctx,
1491                                                             winreg_pipe,
1492                                                             &key_hnd,
1493                                                             SPOOL_REG_PRINTSTARTTIME,
1494                                                             0);
1495                         if (!W_ERROR_IS_OK(result)) {
1496                                 goto done;
1497                         }
1498
1499                         result = winreg_printer_write_dword(tmp_ctx,
1500                                                             winreg_pipe,
1501                                                             &key_hnd,
1502                                                             SPOOL_REG_PRINTENDTIME,
1503                                                             0);
1504                         if (!W_ERROR_IS_OK(result)) {
1505                                 goto done;
1506                         }
1507
1508                         result = winreg_printer_write_dword(tmp_ctx,
1509                                                             winreg_pipe,
1510                                                             &key_hnd,
1511                                                             SPOOL_REG_PRIORITY,
1512                                                             1);
1513                         if (!W_ERROR_IS_OK(result)) {
1514                                 goto done;
1515                         }
1516
1517                         result = winreg_printer_write_dword(tmp_ctx,
1518                                                             winreg_pipe,
1519                                                             &key_hnd,
1520                                                             SPOOL_REG_PRINTKEEPPRINTEDJOBS,
1521                                                             0);
1522                         if (!W_ERROR_IS_OK(result)) {
1523                                 goto done;
1524                         }
1525                 } /* case 1 */
1526                 default:
1527                         break;
1528                 }
1529
1530                 if (is_valid_policy_hnd(&key_hnd)) {
1531                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1532                 }
1533         }
1534         info2 = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
1535         if (info2 == NULL) {
1536                 result = WERR_NOMEM;
1537                 goto done;
1538         }
1539
1540         if (servername != NULL) {
1541                 info2->printername = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
1542                                                      servername, sharename);
1543         } else {
1544                 info2->printername = sharename;
1545         }
1546         if (info2->printername == NULL) {
1547                 result = WERR_NOMEM;
1548                 goto done;
1549         }
1550         info2_mask |= SPOOLSS_PRINTER_INFO_PRINTERNAME;
1551
1552         info2->sharename = sharename;
1553         info2_mask |= SPOOLSS_PRINTER_INFO_SHARENAME;
1554
1555         info2->portname = SAMBA_PRINTER_PORT_NAME;
1556         info2_mask |= SPOOLSS_PRINTER_INFO_PORTNAME;
1557
1558         info2->printprocessor = "winprint";
1559         info2_mask |= SPOOLSS_PRINTER_INFO_PRINTPROCESSOR;
1560
1561         info2->datatype = "RAW";
1562         info2_mask |= SPOOLSS_PRINTER_INFO_DATATYPE;
1563
1564         info2->comment = "";
1565         info2_mask |= SPOOLSS_PRINTER_INFO_COMMENT;
1566
1567         info2->attributes = PRINTER_ATTRIBUTE_SAMBA;
1568         info2_mask |= SPOOLSS_PRINTER_INFO_ATTRIBUTES;
1569
1570         info2->starttime = 0; /* Minutes since 12:00am GMT */
1571         info2_mask |= SPOOLSS_PRINTER_INFO_STARTTIME;
1572
1573         info2->untiltime = 0; /* Minutes since 12:00am GMT */
1574         info2_mask |= SPOOLSS_PRINTER_INFO_UNTILTIME;
1575
1576         info2->priority = 1;
1577         info2_mask |= SPOOLSS_PRINTER_INFO_PRIORITY;
1578
1579         info2->defaultpriority = 1;
1580         info2_mask |= SPOOLSS_PRINTER_INFO_DEFAULTPRIORITY;
1581
1582         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
1583         if (!W_ERROR_IS_OK(result)) {
1584                 goto done;
1585         }
1586         info2_mask |= SPOOLSS_PRINTER_INFO_SECDESC;
1587
1588         /*
1589          * Don't write a default Device Mode to the registry! The Device Mode is
1590          * only written to disk with a SetPrinter level 2 or 8.
1591          */
1592
1593         result = winreg_update_printer(tmp_ctx,
1594                                        server_info,
1595                                        sharename,
1596                                        info2_mask,
1597                                        info2,
1598                                        NULL,
1599                                        secdesc);
1600
1601 done:
1602         if (winreg_pipe != NULL) {
1603                 if (is_valid_policy_hnd(&key_hnd)) {
1604                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1605                 }
1606                 if (is_valid_policy_hnd(&hive_hnd)) {
1607                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1608                 }
1609         }
1610
1611         talloc_free(tmp_ctx);
1612         return result;
1613 }
1614
1615 WERROR winreg_update_printer(TALLOC_CTX *mem_ctx,
1616                              struct auth_serversupplied_info *server_info,
1617                              const char *sharename,
1618                              uint32_t info2_mask,
1619                              struct spoolss_SetPrinterInfo2 *info2,
1620                              struct spoolss_DeviceMode *devmode,
1621                              struct security_descriptor *secdesc)
1622 {
1623         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1624         struct rpc_pipe_client *winreg_pipe = NULL;
1625         struct policy_handle hive_hnd, key_hnd;
1626         int snum = lp_servicenumber(sharename);
1627         enum ndr_err_code ndr_err;
1628         DATA_BLOB blob;
1629         char *path;
1630         WERROR result = WERR_OK;
1631         TALLOC_CTX *tmp_ctx;
1632
1633         tmp_ctx = talloc_new(mem_ctx);
1634         if (tmp_ctx == NULL) {
1635                 return WERR_NOMEM;
1636         }
1637
1638         path = winreg_printer_data_keyname(tmp_ctx, sharename);
1639         if (path == NULL) {
1640                 TALLOC_FREE(tmp_ctx);
1641                 return WERR_NOMEM;
1642         }
1643
1644         ZERO_STRUCT(hive_hnd);
1645         ZERO_STRUCT(key_hnd);
1646
1647         result = winreg_printer_openkey(tmp_ctx,
1648                                         server_info,
1649                                         &winreg_pipe,
1650                                         path,
1651                                         "",
1652                                         true,
1653                                         access_mask,
1654                                         &hive_hnd,
1655                                         &key_hnd);
1656         if (!W_ERROR_IS_OK(result)) {
1657                 DEBUG(0, ("winreg_update_printer: Could not open key %s: %s\n",
1658                         path, win_errstr(result)));
1659                 goto done;
1660         }
1661
1662         if (info2_mask & SPOOLSS_PRINTER_INFO_ATTRIBUTES) {
1663                 result = winreg_printer_write_dword(tmp_ctx,
1664                                                     winreg_pipe,
1665                                                     &key_hnd,
1666                                                     "Attributes",
1667                                                     info2->attributes);
1668                 if (!W_ERROR_IS_OK(result)) {
1669                         goto done;
1670                 }
1671         }
1672
1673 #if 0
1674         if (info2_mask & SPOOLSS_PRINTER_INFO_AVERAGEPPM) {
1675                 result = winreg_printer_write_dword(tmp_ctx,
1676                                                     winreg_pipe,
1677                                                     &key_hnd,
1678                                                     "AveragePpm",
1679                                                     info2->attributes);
1680                 if (!W_ERROR_IS_OK(result)) {
1681                         goto done;
1682                 }
1683         }
1684 #endif
1685
1686         if (info2_mask & SPOOLSS_PRINTER_INFO_COMMENT) {
1687                 result = winreg_printer_write_sz(tmp_ctx,
1688                                                  winreg_pipe,
1689                                                  &key_hnd,
1690                                                  "Description",
1691                                                  info2->comment);
1692                 if (!W_ERROR_IS_OK(result)) {
1693                         goto done;
1694                 }
1695         }
1696
1697         if (info2_mask & SPOOLSS_PRINTER_INFO_DATATYPE) {
1698                 result = winreg_printer_write_sz(tmp_ctx,
1699                                                  winreg_pipe,
1700                                                  &key_hnd,
1701                                                  "Datatype",
1702                                                  info2->datatype);
1703                 if (!W_ERROR_IS_OK(result)) {
1704                         goto done;
1705                 }
1706         }
1707
1708         if (info2_mask & SPOOLSS_PRINTER_INFO_DEFAULTPRIORITY) {
1709                 result = winreg_printer_write_dword(tmp_ctx,
1710                                                     winreg_pipe,
1711                                                     &key_hnd,
1712                                                     "Default Priority",
1713                                                     info2->defaultpriority);
1714                 if (!W_ERROR_IS_OK(result)) {
1715                         goto done;
1716                 }
1717         }
1718
1719         if (info2_mask & SPOOLSS_PRINTER_INFO_DEVMODE) {
1720                 /*
1721                  * Some client drivers freak out if there is a NULL devmode
1722                  * (probably the driver is not checking before accessing
1723                  * the devmode pointer)   --jerry
1724                  */
1725                 if (devmode == NULL && lp_default_devmode(snum) && info2 != NULL) {
1726                         result = spoolss_create_default_devmode(tmp_ctx,
1727                                                                 info2->printername,
1728                                                                 &devmode);
1729                         if (!W_ERROR_IS_OK(result)) {
1730                                 goto done;
1731                         }
1732                 }
1733                 ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, devmode,
1734                                 (ndr_push_flags_fn_t) ndr_push_spoolss_DeviceMode);
1735                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1736                         DEBUG(0, ("winreg_update_printer: Failed to marshall device mode\n"));
1737                         result = WERR_NOMEM;
1738                         goto done;
1739                 }
1740
1741                 result = winreg_printer_write_binary(tmp_ctx,
1742                                                      winreg_pipe,
1743                                                      &key_hnd,
1744                                                      "Default DevMode",
1745                                                      blob);
1746                 if (!W_ERROR_IS_OK(result)) {
1747                         goto done;
1748                 }
1749         }
1750
1751         if (info2_mask & SPOOLSS_PRINTER_INFO_DRIVERNAME) {
1752                 result = winreg_printer_write_sz(tmp_ctx,
1753                                                  winreg_pipe,
1754                                                  &key_hnd,
1755                                                  "Printer Driver",
1756                                                  info2->drivername);
1757                 if (!W_ERROR_IS_OK(result)) {
1758                         goto done;
1759                 }
1760         }
1761
1762         if (info2_mask & SPOOLSS_PRINTER_INFO_LOCATION) {
1763                 result = winreg_printer_write_sz(tmp_ctx,
1764                                                  winreg_pipe,
1765                                                  &key_hnd,
1766                                                  "Location",
1767                                                  info2->location);
1768                 if (!W_ERROR_IS_OK(result)) {
1769                         goto done;
1770                 }
1771         }
1772
1773         if (info2_mask & SPOOLSS_PRINTER_INFO_PARAMETERS) {
1774                 result = winreg_printer_write_sz(tmp_ctx,
1775                                                  winreg_pipe,
1776                                                  &key_hnd,
1777                                                  "Parameters",
1778                                                  info2->parameters);
1779                 if (!W_ERROR_IS_OK(result)) {
1780                         goto done;
1781                 }
1782         }
1783
1784         if (info2_mask & SPOOLSS_PRINTER_INFO_PORTNAME) {
1785                 result = winreg_printer_write_sz(tmp_ctx,
1786                                                  winreg_pipe,
1787                                                  &key_hnd,
1788                                                  "Port",
1789                                                  info2->portname);
1790                 if (!W_ERROR_IS_OK(result)) {
1791                         goto done;
1792                 }
1793         }
1794
1795         if (info2_mask & SPOOLSS_PRINTER_INFO_PRINTERNAME) {
1796                 /*
1797                  * in addprinter: no servername and the printer is the name
1798                  * in setprinter: servername is \\server
1799                  *                and printer is \\server\\printer
1800                  *
1801                  * Samba manages only local printers.
1802                  * we currently don't support things like i
1803                  * path=\\other_server\printer
1804                  *
1805                  * We only store the printername, not \\server\printername
1806                  */
1807                 const char *p = strrchr(info2->printername, '\\');
1808                 if (p == NULL) {
1809                         p = info2->printername;
1810                 } else {
1811                         p++;
1812                 }
1813                 result = winreg_printer_write_sz(tmp_ctx,
1814                                                  winreg_pipe,
1815                                                  &key_hnd,
1816                                                  "Name",
1817                                                  p);
1818                 if (!W_ERROR_IS_OK(result)) {
1819                         goto done;
1820                 }
1821         }
1822
1823         if (info2_mask & SPOOLSS_PRINTER_INFO_PRINTPROCESSOR) {
1824                 result = winreg_printer_write_sz(tmp_ctx,
1825                                                  winreg_pipe,
1826                                                  &key_hnd,
1827                                                  "Print Processor",
1828                                                  info2->printprocessor);
1829                 if (!W_ERROR_IS_OK(result)) {
1830                         goto done;
1831                 }
1832         }
1833
1834         if (info2_mask & SPOOLSS_PRINTER_INFO_PRIORITY) {
1835                 result = winreg_printer_write_dword(tmp_ctx,
1836                                                     winreg_pipe,
1837                                                     &key_hnd,
1838                                                     "Priority",
1839                                                     info2->priority);
1840                 if (!W_ERROR_IS_OK(result)) {
1841                         goto done;
1842                 }
1843         }
1844
1845         if (info2_mask & SPOOLSS_PRINTER_INFO_SECDESC) {
1846                 /*
1847                  * We need a security descriptor, if it isn't specified by
1848                  * AddPrinter{Ex} then create a default descriptor.
1849                  */
1850                 if (secdesc == NULL) {
1851                         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
1852                         if (!W_ERROR_IS_OK(result)) {
1853                                 goto done;
1854                         }
1855                 }
1856                 result = winreg_set_printer_secdesc(tmp_ctx,
1857                                                     server_info,
1858                                                     sharename,
1859                                                     secdesc);
1860                 if (!W_ERROR_IS_OK(result)) {
1861                         goto done;
1862                 }
1863         }
1864
1865         if (info2_mask & SPOOLSS_PRINTER_INFO_SEPFILE) {
1866                 result = winreg_printer_write_sz(tmp_ctx,
1867                                                  winreg_pipe,
1868                                                  &key_hnd,
1869                                                  "Separator File",
1870                                                  info2->sepfile);
1871                 if (!W_ERROR_IS_OK(result)) {
1872                         goto done;
1873                 }
1874         }
1875
1876         if (info2_mask & SPOOLSS_PRINTER_INFO_SHARENAME) {
1877                 result = winreg_printer_write_sz(tmp_ctx,
1878                                                  winreg_pipe,
1879                                                  &key_hnd,
1880                                                  "Share Name",
1881                                                  info2->sharename);
1882                 if (!W_ERROR_IS_OK(result)) {
1883                         goto done;
1884                 }
1885         }
1886
1887         if (info2_mask & SPOOLSS_PRINTER_INFO_STARTTIME) {
1888                 result = winreg_printer_write_dword(tmp_ctx,
1889                                                     winreg_pipe,
1890                                                     &key_hnd,
1891                                                     "StartTime",
1892                                                     info2->starttime);
1893                 if (!W_ERROR_IS_OK(result)) {
1894                         goto done;
1895                 }
1896         }
1897
1898         if (info2_mask & SPOOLSS_PRINTER_INFO_STATUS) {
1899                 result = winreg_printer_write_dword(tmp_ctx,
1900                                                     winreg_pipe,
1901                                                     &key_hnd,
1902                                                     "Status",
1903                                                     info2->status);
1904                 if (!W_ERROR_IS_OK(result)) {
1905                         goto done;
1906                 }
1907         }
1908
1909         if (info2_mask & SPOOLSS_PRINTER_INFO_UNTILTIME) {
1910                 result = winreg_printer_write_dword(tmp_ctx,
1911                                                     winreg_pipe,
1912                                                     &key_hnd,
1913                                                     "UntilTime",
1914                                                     info2->untiltime);
1915                 if (!W_ERROR_IS_OK(result)) {
1916                         goto done;
1917                 }
1918         }
1919
1920         result = winreg_printer_write_dword(tmp_ctx,
1921                                             winreg_pipe,
1922                                             &key_hnd,
1923                                             "ChangeID",
1924                                             winreg_printer_rev_changeid());
1925         if (!W_ERROR_IS_OK(result)) {
1926                 goto done;
1927         }
1928
1929         result = WERR_OK;
1930 done:
1931         if (winreg_pipe != NULL) {
1932                 if (is_valid_policy_hnd(&key_hnd)) {
1933                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
1934                 }
1935                 if (is_valid_policy_hnd(&hive_hnd)) {
1936                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
1937                 }
1938         }
1939
1940         TALLOC_FREE(tmp_ctx);
1941         return result;
1942 }
1943
1944 WERROR winreg_get_printer(TALLOC_CTX *mem_ctx,
1945                           struct auth_serversupplied_info *server_info,
1946                           const char *servername,
1947                           const char *printer,
1948                           struct spoolss_PrinterInfo2 **pinfo2)
1949 {
1950         struct spoolss_PrinterInfo2 *info2;
1951         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1952         struct rpc_pipe_client *winreg_pipe = NULL;
1953         struct policy_handle hive_hnd, key_hnd;
1954         struct spoolss_PrinterEnumValues *enum_values = NULL;
1955         struct spoolss_PrinterEnumValues *v;
1956         enum ndr_err_code ndr_err;
1957         DATA_BLOB blob;
1958         int snum = lp_servicenumber(printer);
1959         uint32_t num_values = 0;
1960         uint32_t i;
1961         char *path;
1962         WERROR result = WERR_OK;
1963         TALLOC_CTX *tmp_ctx;
1964
1965         tmp_ctx = talloc_new(mem_ctx);
1966         if (tmp_ctx == NULL) {
1967                 return WERR_NOMEM;
1968         }
1969
1970         path = winreg_printer_data_keyname(tmp_ctx, printer);
1971         if (path == NULL) {
1972                 TALLOC_FREE(tmp_ctx);
1973                 return WERR_NOMEM;
1974         }
1975
1976         result = winreg_printer_openkey(tmp_ctx,
1977                                         server_info,
1978                                         &winreg_pipe,
1979                                         path,
1980                                         "",
1981                                         false,
1982                                         access_mask,
1983                                         &hive_hnd,
1984                                         &key_hnd);
1985         if (!W_ERROR_IS_OK(result)) {
1986                 DEBUG(0, ("winreg_get_printer: Could not open key %s: %s\n",
1987                           path, win_errstr(result)));
1988                 goto done;
1989         }
1990
1991         result = winreg_printer_enumvalues(tmp_ctx,
1992                                            winreg_pipe,
1993                                            &key_hnd,
1994                                            &num_values,
1995                                            &enum_values);
1996         if (!W_ERROR_IS_OK(result)) {
1997                 DEBUG(0, ("winreg_get_printer: Could not enumerate values in %s: %s\n",
1998                           path, win_errstr(result)));
1999                 goto done;
2000         }
2001
2002         info2 = talloc_zero(tmp_ctx, struct spoolss_PrinterInfo2);
2003         if (info2 == NULL) {
2004                 result = WERR_NOMEM;
2005                 goto done;
2006         }
2007
2008         FILL_STRING(info2, EMPTY_STRING, info2->servername);
2009         FILL_STRING(info2, EMPTY_STRING, info2->printername);
2010         FILL_STRING(info2, EMPTY_STRING, info2->sharename);
2011         FILL_STRING(info2, EMPTY_STRING, info2->portname);
2012         FILL_STRING(info2, EMPTY_STRING, info2->drivername);
2013         FILL_STRING(info2, EMPTY_STRING, info2->comment);
2014         FILL_STRING(info2, EMPTY_STRING, info2->location);
2015         FILL_STRING(info2, EMPTY_STRING, info2->sepfile);
2016         FILL_STRING(info2, EMPTY_STRING, info2->printprocessor);
2017         FILL_STRING(info2, EMPTY_STRING, info2->datatype);
2018         FILL_STRING(info2, EMPTY_STRING, info2->parameters);
2019
2020         if (servername != NULL && servername[0] != '\0') {
2021                 info2->servername = talloc_asprintf(info2, "\\\\%s", servername);
2022                 if (info2->servername == NULL) {
2023                         result = WERR_NOMEM;
2024                         goto done;
2025                 }
2026         }
2027
2028         for (i = 0; i < num_values; i++) {
2029                 v = &enum_values[i];
2030
2031                 result = winreg_enumval_to_sz(info2,
2032                                               v,
2033                                               "Name",
2034                                               &info2->printername);
2035                 CHECK_ERROR(result);
2036
2037                 result = winreg_enumval_to_sz(info2,
2038                                               v,
2039                                               "Share Name",
2040                                               &info2->sharename);
2041                 CHECK_ERROR(result);
2042
2043                 result = winreg_enumval_to_sz(info2,
2044                                               v,
2045                                               "Port",
2046                                               &info2->portname);
2047                 CHECK_ERROR(result);
2048
2049                 result = winreg_enumval_to_sz(info2,
2050                                               v,
2051                                               "Description",
2052                                               &info2->comment);
2053                 CHECK_ERROR(result);
2054
2055                 result = winreg_enumval_to_sz(info2,
2056                                               v,
2057                                               "Location",
2058                                               &info2->location);
2059                 CHECK_ERROR(result);
2060
2061                 result = winreg_enumval_to_sz(info2,
2062                                               v,
2063                                               "Separator File",
2064                                               &info2->sepfile);
2065                 CHECK_ERROR(result);
2066
2067                 result = winreg_enumval_to_sz(info2,
2068                                               v,
2069                                               "Print Processor",
2070                                               &info2->printprocessor);
2071                 CHECK_ERROR(result);
2072
2073                 result = winreg_enumval_to_sz(info2,
2074                                               v,
2075                                               "Datatype",
2076                                               &info2->datatype);
2077                 CHECK_ERROR(result);
2078
2079                 result = winreg_enumval_to_sz(info2,
2080                                               v,
2081                                               "Parameters",
2082                                               &info2->parameters);
2083                 CHECK_ERROR(result);
2084
2085                 result = winreg_enumval_to_sz(info2,
2086                                               v,
2087                                               "Printer Driver",
2088                                               &info2->drivername);
2089                 CHECK_ERROR(result);
2090
2091                 result = winreg_enumval_to_dword(info2,
2092                                                  v,
2093                                                  "Attributes",
2094                                                  &info2->attributes);
2095                 CHECK_ERROR(result);
2096
2097                 result = winreg_enumval_to_dword(info2,
2098                                                  v,
2099                                                  "Priority",
2100                                                  &info2->priority);
2101                 CHECK_ERROR(result);
2102
2103                 result = winreg_enumval_to_dword(info2,
2104                                                  v,
2105                                                  "Default Priority",
2106                                                  &info2->defaultpriority);
2107                 CHECK_ERROR(result);
2108
2109                 result = winreg_enumval_to_dword(info2,
2110                                                  v,
2111                                                  "StartTime",
2112                                                  &info2->starttime);
2113                 CHECK_ERROR(result);
2114
2115                 result = winreg_enumval_to_dword(info2,
2116                                                  v,
2117                                                  "UntilTime",
2118                                                  &info2->untiltime);
2119                 CHECK_ERROR(result);
2120
2121                 result = winreg_enumval_to_dword(info2,
2122                                                  v,
2123                                                  "Status",
2124                                                  &info2->status);
2125                 CHECK_ERROR(result);
2126
2127                 result = winreg_enumval_to_dword(info2,
2128                                                  v,
2129                                                  "StartTime",
2130                                                  &info2->starttime);
2131                 CHECK_ERROR(result);
2132         }
2133
2134         if (!W_ERROR_IS_OK(result)) {
2135                 DEBUG(0, ("winreg_get_printer: winreg_enumval_to_TYPE() failed "
2136                                         "for %s: %s\n",
2137                                         v->value_name,
2138                                         win_errstr(result)));
2139                 goto done;
2140         }
2141
2142         /* Create the printername */
2143         if (info2->servername != NULL && info2->servername[0] != '\0') {
2144                 if (lp_force_printername(snum)) {
2145                         const char *p = talloc_asprintf(info2, "%s\\%s",
2146                                                         info2->servername,
2147                                                         info2->sharename);
2148                                 if (p == NULL) {
2149                                         result = WERR_NOMEM;
2150                                         goto done;
2151                                 }
2152                                 info2->printername = p;
2153                 } else {
2154                         char *p = talloc_asprintf(info2, "%s\\%s",
2155                                                   info2->servername,
2156                                                   info2->printername);
2157                         if (p == NULL) {
2158                                 result = WERR_NOMEM;
2159                                 goto done;
2160                         }
2161                         info2->printername = p;
2162                 }
2163         }
2164
2165         /* Construct the Device Mode */
2166         result = winreg_printer_query_binary(tmp_ctx,
2167                                              winreg_pipe,
2168                                              &key_hnd,
2169                                              "Default DevMode",
2170                                              &blob);
2171         if (W_ERROR_IS_OK(result)) {
2172                 info2->devmode = talloc_zero(info2, struct spoolss_DeviceMode);
2173                 if (info2->devmode == NULL) {
2174                         result = WERR_NOMEM;
2175                         goto done;
2176                 }
2177                 ndr_err = ndr_pull_struct_blob(&blob,
2178                                                info2->devmode,
2179                                                info2->devmode,
2180                                                (ndr_pull_flags_fn_t) ndr_pull_spoolss_DeviceMode);
2181                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2182                         DEBUG(0, ("winreg_get_printer: Failed to unmarshall device mode\n"));
2183                         result = WERR_NOMEM;
2184                         goto done;
2185                 }
2186         }
2187
2188         if (info2->devmode == NULL && lp_default_devmode(snum)) {
2189                 result = spoolss_create_default_devmode(info2,
2190                                                         info2->printername,
2191                                                         &info2->devmode);
2192                 if (!W_ERROR_IS_OK(result)) {
2193                         goto done;
2194                 }
2195         }
2196
2197         if (info2->devmode != NULL) {
2198                 info2->devmode->devicename = talloc_strdup(info2->devmode,
2199                                                            info2->printername);
2200                 if (info2->devmode->devicename == NULL) {
2201                         DEBUG(0, ("winreg_get_printer: Failed to set devicename\n"));
2202                         result = WERR_NOMEM;
2203                         goto done;
2204                 }
2205         }
2206
2207         result = winreg_get_printer_secdesc(info2,
2208                                             server_info,
2209                                             printer,
2210                                             &info2->secdesc);
2211         if (!W_ERROR_IS_OK(result)) {
2212                 goto done;
2213         }
2214
2215         /* Fix for OS/2 drivers. */
2216         if (get_remote_arch() == RA_OS2) {
2217                 spoolss_map_to_os2_driver(info2, &info2->drivername);
2218         }
2219
2220         if (pinfo2) {
2221                 *pinfo2 = talloc_move(mem_ctx, &info2);
2222         }
2223
2224         result = WERR_OK;
2225 done:
2226         if (winreg_pipe != NULL) {
2227                 if (is_valid_policy_hnd(&key_hnd)) {
2228                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2229                 }
2230                 if (is_valid_policy_hnd(&hive_hnd)) {
2231                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2232                 }
2233         }
2234
2235         TALLOC_FREE(tmp_ctx);
2236         return result;
2237 }
2238
2239 WERROR winreg_get_printer_secdesc(TALLOC_CTX *mem_ctx,
2240                                   struct auth_serversupplied_info *server_info,
2241                                   const char *sharename,
2242                                   struct spoolss_security_descriptor **psecdesc)
2243 {
2244         struct spoolss_security_descriptor *secdesc;
2245         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2246         struct rpc_pipe_client *winreg_pipe = NULL;
2247         struct policy_handle hive_hnd, key_hnd;
2248         enum ndr_err_code ndr_err;
2249         const char *path;
2250         DATA_BLOB blob;
2251         TALLOC_CTX *tmp_ctx;
2252         WERROR result;
2253
2254         tmp_ctx = talloc_new(mem_ctx);
2255         if (tmp_ctx == NULL) {
2256                 return WERR_NOMEM;
2257         }
2258
2259         path = winreg_printer_data_keyname(tmp_ctx, sharename);
2260         if (path == NULL) {
2261                 talloc_free(tmp_ctx);
2262                 return WERR_NOMEM;
2263         }
2264
2265         ZERO_STRUCT(hive_hnd);
2266         ZERO_STRUCT(key_hnd);
2267
2268         result = winreg_printer_openkey(tmp_ctx,
2269                                         server_info,
2270                                         &winreg_pipe,
2271                                         path,
2272                                         "",
2273                                         false,
2274                                         access_mask,
2275                                         &hive_hnd,
2276                                         &key_hnd);
2277         if (!W_ERROR_IS_OK(result)) {
2278                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2279                         goto create_default;
2280                 }
2281                 goto done;
2282         }
2283
2284         result = winreg_printer_query_binary(tmp_ctx,
2285                                              winreg_pipe,
2286                                              &key_hnd,
2287                                              "Security",
2288                                              &blob);
2289         if (!W_ERROR_IS_OK(result)) {
2290                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2291                         goto create_default;
2292                 }
2293                 goto done;
2294         }
2295
2296         secdesc = talloc_zero(tmp_ctx, struct spoolss_security_descriptor);
2297         if (secdesc == NULL) {
2298                 result = WERR_NOMEM;
2299                 goto done;
2300         }
2301         ndr_err = ndr_pull_struct_blob(&blob,
2302                                        secdesc,
2303                                        secdesc,
2304                                        (ndr_pull_flags_fn_t) ndr_pull_security_descriptor);
2305         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2306                 DEBUG(0, ("winreg_get_secdesc: Failed to unmarshall security descriptor\n"));
2307                 result = WERR_NOMEM;
2308                 goto done;
2309         }
2310
2311         if (psecdesc) {
2312                 *psecdesc = talloc_move(mem_ctx, &secdesc);
2313         }
2314
2315         result = WERR_OK;
2316         goto done;
2317
2318 create_default:
2319         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
2320         if (!W_ERROR_IS_OK(result)) {
2321                 return result;
2322         }
2323
2324         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
2325            this security descriptor has been created when winbindd was
2326            down.  Take ownership of security descriptor. */
2327         if (sid_equal(secdesc->owner_sid, &global_sid_World)) {
2328                 struct dom_sid owner_sid;
2329
2330                 /* Change sd owner to workgroup administrator */
2331
2332                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
2333                         struct spoolss_security_descriptor *new_secdesc;
2334                         size_t size;
2335
2336                         /* Create new sd */
2337                         sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
2338
2339                         new_secdesc = make_sec_desc(tmp_ctx,
2340                                                     secdesc->revision,
2341                                                     secdesc->type,
2342                                                     &owner_sid,
2343                                                     secdesc->group_sid,
2344                                                     secdesc->sacl,
2345                                                     secdesc->dacl,
2346                                                     &size);
2347
2348                         if (new_secdesc == NULL) {
2349                                 result = WERR_NOMEM;
2350                                 goto done;
2351                         }
2352
2353                         /* Swap with other one */
2354                         secdesc = new_secdesc;
2355                 }
2356         }
2357
2358         ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, secdesc,
2359                         (ndr_push_flags_fn_t) ndr_push_security_descriptor);
2360         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2361                 DEBUG(0, ("winreg_set_secdesc: Failed to marshall security descriptor\n"));
2362                 result = WERR_NOMEM;
2363                 goto done;
2364         }
2365
2366         result = winreg_printer_write_binary(tmp_ctx,
2367                                              winreg_pipe,
2368                                              &key_hnd,
2369                                              "Security",
2370                                              blob);
2371         if (!W_ERROR_IS_OK(result)) {
2372                 return result;
2373         }
2374
2375         if (psecdesc) {
2376                 *psecdesc = talloc_move(mem_ctx, &secdesc);
2377         }
2378
2379         result = WERR_OK;
2380 done:
2381         if (winreg_pipe != NULL) {
2382                 if (is_valid_policy_hnd(&key_hnd)) {
2383                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2384                 }
2385                 if (is_valid_policy_hnd(&hive_hnd)) {
2386                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2387                 }
2388         }
2389
2390         talloc_free(tmp_ctx);
2391         return result;
2392 }
2393
2394 WERROR winreg_set_printer_secdesc(TALLOC_CTX *mem_ctx,
2395                                   struct auth_serversupplied_info *server_info,
2396                                   const char *sharename,
2397                                   const struct spoolss_security_descriptor *secdesc)
2398 {
2399         const struct spoolss_security_descriptor *new_secdesc = secdesc;
2400         struct spoolss_security_descriptor *old_secdesc;
2401         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2402         struct rpc_pipe_client *winreg_pipe = NULL;
2403         struct policy_handle hive_hnd, key_hnd;
2404         enum ndr_err_code ndr_err;
2405         const char *path;
2406         DATA_BLOB blob;
2407         TALLOC_CTX *tmp_ctx;
2408         WERROR result;
2409
2410         tmp_ctx = talloc_new(mem_ctx);
2411         if (tmp_ctx == NULL) {
2412                 return WERR_NOMEM;
2413         }
2414
2415         path = winreg_printer_data_keyname(tmp_ctx, sharename);
2416         if (path == NULL) {
2417                 talloc_free(tmp_ctx);
2418                 return WERR_NOMEM;
2419         }
2420
2421         /*
2422          * The old owner and group sids of the security descriptor are not
2423          * present when new ACEs are added or removed by changing printer
2424          * permissions through NT.  If they are NULL in the new security
2425          * descriptor then copy them over from the old one.
2426          */
2427         if (!secdesc->owner_sid || !secdesc->group_sid) {
2428                 struct dom_sid *owner_sid, *group_sid;
2429                 struct security_acl *dacl, *sacl;
2430                 size_t size;
2431
2432                 result = winreg_get_printer_secdesc(tmp_ctx,
2433                                                     server_info,
2434                                                     sharename,
2435                                                     &old_secdesc);
2436                 if (!W_ERROR_IS_OK(result)) {
2437                         talloc_free(tmp_ctx);
2438                         return result;
2439                 }
2440
2441                 /* Pick out correct owner and group sids */
2442                 owner_sid = secdesc->owner_sid ?
2443                             secdesc->owner_sid :
2444                             old_secdesc->owner_sid;
2445
2446                 group_sid = secdesc->group_sid ?
2447                             secdesc->group_sid :
2448                             old_secdesc->group_sid;
2449
2450                 dacl = secdesc->dacl ?
2451                        secdesc->dacl :
2452                        old_secdesc->dacl;
2453
2454                 sacl = secdesc->sacl ?
2455                        secdesc->sacl :
2456                        old_secdesc->sacl;
2457
2458                 /* Make a deep copy of the security descriptor */
2459                 new_secdesc = make_sec_desc(tmp_ctx,
2460                                             secdesc->revision,
2461                                             secdesc->type,
2462                                             owner_sid,
2463                                             group_sid,
2464                                             sacl,
2465                                             dacl,
2466                                             &size);
2467                 if (new_secdesc == NULL) {
2468                         talloc_free(tmp_ctx);
2469                         return WERR_NOMEM;
2470                 }
2471         }
2472
2473         ZERO_STRUCT(hive_hnd);
2474         ZERO_STRUCT(key_hnd);
2475
2476         result = winreg_printer_openkey(tmp_ctx,
2477                                         server_info,
2478                                         &winreg_pipe,
2479                                         path,
2480                                         "",
2481                                         false,
2482                                         access_mask,
2483                                         &hive_hnd,
2484                                         &key_hnd);
2485         if (!W_ERROR_IS_OK(result)) {
2486                 goto done;
2487         }
2488
2489         ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, new_secdesc,
2490                         (ndr_push_flags_fn_t) ndr_push_security_descriptor);
2491         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2492                 DEBUG(0, ("winreg_set_secdesc: Failed to marshall security descriptor\n"));
2493                 result = WERR_NOMEM;
2494                 goto done;
2495         }
2496
2497         result = winreg_printer_write_binary(tmp_ctx,
2498                                              winreg_pipe,
2499                                              &key_hnd,
2500                                              "Security",
2501                                              blob);
2502
2503 done:
2504         if (winreg_pipe != NULL) {
2505                 if (is_valid_policy_hnd(&key_hnd)) {
2506                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2507                 }
2508                 if (is_valid_policy_hnd(&hive_hnd)) {
2509                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2510                 }
2511         }
2512
2513         talloc_free(tmp_ctx);
2514         return result;
2515 }
2516
2517 /* Set printer data over the winreg pipe. */
2518 WERROR winreg_set_printer_dataex(TALLOC_CTX *mem_ctx,
2519                                  struct auth_serversupplied_info *server_info,
2520                                  const char *printer,
2521                                  const char *key,
2522                                  const char *value,
2523                                  enum winreg_Type type,
2524                                  uint8_t *data,
2525                                  uint32_t data_size)
2526 {
2527         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2528         struct rpc_pipe_client *winreg_pipe = NULL;
2529         struct policy_handle hive_hnd, key_hnd;
2530         struct winreg_String wvalue;
2531         char *path;
2532         WERROR result = WERR_OK;
2533         NTSTATUS status;
2534         TALLOC_CTX *tmp_ctx;
2535
2536         tmp_ctx = talloc_new(mem_ctx);
2537         if (tmp_ctx == NULL) {
2538                 return WERR_NOMEM;
2539         }
2540
2541         path = winreg_printer_data_keyname(tmp_ctx, printer);
2542         if (path == NULL) {
2543                 TALLOC_FREE(tmp_ctx);
2544                 return WERR_NOMEM;
2545         }
2546
2547         ZERO_STRUCT(hive_hnd);
2548         ZERO_STRUCT(key_hnd);
2549
2550         DEBUG(8, ("winreg_set_printer_dataex: Open printer key %s, value %s, access_mask: 0x%05x for [%s]\n",
2551                         key, value, access_mask, printer));
2552         result = winreg_printer_openkey(tmp_ctx,
2553                                         server_info,
2554                                         &winreg_pipe,
2555                                         path,
2556                                         key,
2557                                         true,
2558                                         access_mask,
2559                                         &hive_hnd,
2560                                         &key_hnd);
2561         if (!W_ERROR_IS_OK(result)) {
2562                 DEBUG(0, ("winreg_set_printer_dataex: Could not open key %s: %s\n",
2563                           key, win_errstr(result)));
2564                 goto done;
2565         }
2566
2567         wvalue.name = value;
2568         status = rpccli_winreg_SetValue(winreg_pipe,
2569                                         tmp_ctx,
2570                                         &key_hnd,
2571                                         wvalue,
2572                                         type,
2573                                         data,
2574                                         data_size,
2575                                         &result);
2576         if (!NT_STATUS_IS_OK(status)) {
2577                 DEBUG(0, ("winreg_set_printer_dataex: Could not set value %s: %s\n",
2578                           value, nt_errstr(status)));
2579                 if (!W_ERROR_IS_OK(result)) {
2580                         goto done;
2581                 }
2582                 result = ntstatus_to_werror(status);
2583                 goto done;
2584         }
2585
2586         result = WERR_OK;
2587 done:
2588         if (winreg_pipe != NULL) {
2589                 if (is_valid_policy_hnd(&key_hnd)) {
2590                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2591                 }
2592                 if (is_valid_policy_hnd(&hive_hnd)) {
2593                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2594                 }
2595         }
2596
2597         TALLOC_FREE(tmp_ctx);
2598         return result;
2599 }
2600
2601 /* Get printer data over a winreg pipe. */
2602 WERROR winreg_get_printer_dataex(TALLOC_CTX *mem_ctx,
2603                                  struct auth_serversupplied_info *server_info,
2604                                  const char *printer,
2605                                  const char *key,
2606                                  const char *value,
2607                                  enum winreg_Type *type,
2608                                  uint8_t **data,
2609                                  uint32_t *data_size)
2610 {
2611         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2612         struct rpc_pipe_client *winreg_pipe = NULL;
2613         struct policy_handle hive_hnd, key_hnd;
2614         struct winreg_String wvalue;
2615         enum winreg_Type type_in;
2616         char *path;
2617         uint8_t *data_in;
2618         uint32_t data_in_size = 0;
2619         uint32_t value_len = 0;
2620         WERROR result = WERR_OK;
2621         NTSTATUS status;
2622         TALLOC_CTX *tmp_ctx;
2623
2624         tmp_ctx = talloc_new(mem_ctx);
2625         if (tmp_ctx == NULL) {
2626                 return WERR_NOMEM;
2627         }
2628
2629         path = winreg_printer_data_keyname(tmp_ctx, printer);
2630         if (path == NULL) {
2631                 TALLOC_FREE(tmp_ctx);
2632                 return WERR_NOMEM;
2633         }
2634
2635         ZERO_STRUCT(hive_hnd);
2636         ZERO_STRUCT(key_hnd);
2637
2638         result = winreg_printer_openkey(tmp_ctx,
2639                                         server_info,
2640                                         &winreg_pipe,
2641                                         path,
2642                                         key,
2643                                         false,
2644                                         access_mask,
2645                                         &hive_hnd,
2646                                         &key_hnd);
2647         if (!W_ERROR_IS_OK(result)) {
2648                 DEBUG(0, ("winreg_get_printer_dataex: Could not open key %s: %s\n",
2649                           key, win_errstr(result)));
2650                 goto done;
2651         }
2652
2653         wvalue.name = value;
2654
2655         /*
2656          * call QueryValue once with data == NULL to get the
2657          * needed memory size to be allocated, then allocate
2658          * data buffer and call again.
2659          */
2660         status = rpccli_winreg_QueryValue(winreg_pipe,
2661                                           tmp_ctx,
2662                                           &key_hnd,
2663                                           &wvalue,
2664                                           &type_in,
2665                                           NULL,
2666                                           &data_in_size,
2667                                           &value_len,
2668                                           &result);
2669         if (!NT_STATUS_IS_OK(status)) {
2670                 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2671                           value, nt_errstr(status)));
2672                 if (!W_ERROR_IS_OK(result)) {
2673                         goto done;
2674                 }
2675                 result = ntstatus_to_werror(status);
2676                 goto done;
2677         }
2678
2679         data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
2680         if (data_in == NULL) {
2681                 result = WERR_NOMEM;
2682                 goto done;
2683         }
2684         value_len = 0;
2685
2686         status = rpccli_winreg_QueryValue(winreg_pipe,
2687                                           tmp_ctx,
2688                                           &key_hnd,
2689                                           &wvalue,
2690                                           &type_in,
2691                                           data_in,
2692                                           &data_in_size,
2693                                           &value_len,
2694                                           &result);
2695         if (!NT_STATUS_IS_OK(status)) {
2696                 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2697                           value, nt_errstr(status)));
2698                 if (!W_ERROR_IS_OK(result)) {
2699                         result = ntstatus_to_werror(status);
2700                 }
2701                 goto done;
2702         }
2703
2704         *type = type_in;
2705         *data_size = data_in_size;
2706         if (data_in_size) {
2707                 *data = talloc_move(mem_ctx, &data_in);
2708         }
2709
2710         result = WERR_OK;
2711 done:
2712         if (winreg_pipe != NULL) {
2713                 if (is_valid_policy_hnd(&key_hnd)) {
2714                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2715                 }
2716                 if (is_valid_policy_hnd(&hive_hnd)) {
2717                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2718                 }
2719         }
2720
2721         TALLOC_FREE(tmp_ctx);
2722         return result;
2723 }
2724
2725 /* Enumerate on the values of a given key and provide the data. */
2726 WERROR winreg_enum_printer_dataex(TALLOC_CTX *mem_ctx,
2727                                   struct auth_serversupplied_info *server_info,
2728                                   const char *printer,
2729                                   const char *key,
2730                                   uint32_t *pnum_values,
2731                                   struct spoolss_PrinterEnumValues **penum_values)
2732 {
2733         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2734         struct rpc_pipe_client *winreg_pipe = NULL;
2735         struct policy_handle hive_hnd, key_hnd;
2736
2737         struct spoolss_PrinterEnumValues *enum_values = NULL;
2738         uint32_t num_values = 0;
2739         char *path;
2740         WERROR result = WERR_OK;
2741
2742         TALLOC_CTX *tmp_ctx;
2743
2744         tmp_ctx = talloc_new(mem_ctx);
2745         if (tmp_ctx == NULL) {
2746                 return WERR_NOMEM;
2747         }
2748
2749         path = winreg_printer_data_keyname(tmp_ctx, printer);
2750         if (path == NULL) {
2751                 TALLOC_FREE(tmp_ctx);
2752                 return WERR_NOMEM;
2753         }
2754
2755         result = winreg_printer_openkey(tmp_ctx,
2756                                         server_info,
2757                                         &winreg_pipe,
2758                                         path,
2759                                         key,
2760                                         false,
2761                                         access_mask,
2762                                         &hive_hnd,
2763                                         &key_hnd);
2764         if (!W_ERROR_IS_OK(result)) {
2765                 DEBUG(0, ("winreg_enum_printer_dataex: Could not open key %s: %s\n",
2766                           key, win_errstr(result)));
2767                 goto done;
2768         }
2769
2770         result = winreg_printer_enumvalues(tmp_ctx,
2771                                            winreg_pipe,
2772                                            &key_hnd,
2773                                            &num_values,
2774                                            &enum_values);
2775         if (!W_ERROR_IS_OK(result)) {
2776                 DEBUG(0, ("winreg_enum_printer_dataex: Could not enumerate values in %s: %s\n",
2777                           key, win_errstr(result)));
2778                 goto done;
2779         }
2780
2781         *pnum_values = num_values;
2782         if (penum_values) {
2783                 *penum_values = talloc_move(mem_ctx, &enum_values);
2784         }
2785
2786         result = WERR_OK;
2787 done:
2788         if (winreg_pipe != NULL) {
2789                 if (is_valid_policy_hnd(&key_hnd)) {
2790                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2791                 }
2792                 if (is_valid_policy_hnd(&hive_hnd)) {
2793                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2794                 }
2795         }
2796
2797         TALLOC_FREE(tmp_ctx);
2798         return result;
2799 }
2800
2801 /* Delete printer data over a winreg pipe. */
2802 WERROR winreg_delete_printer_dataex(TALLOC_CTX *mem_ctx,
2803                                     struct auth_serversupplied_info *server_info,
2804                                     const char *printer,
2805                                     const char *key,
2806                                     const char *value)
2807 {
2808         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2809         struct rpc_pipe_client *winreg_pipe = NULL;
2810         struct policy_handle hive_hnd, key_hnd;
2811         struct winreg_String wvalue;
2812         char *path;
2813         WERROR result = WERR_OK;
2814         NTSTATUS status;
2815
2816         TALLOC_CTX *tmp_ctx;
2817
2818         tmp_ctx = talloc_new(mem_ctx);
2819         if (tmp_ctx == NULL) {
2820                 return WERR_NOMEM;
2821         }
2822
2823         path = winreg_printer_data_keyname(tmp_ctx, printer);
2824         if (path == NULL) {
2825                 TALLOC_FREE(tmp_ctx);
2826                 return WERR_NOMEM;
2827         }
2828
2829         ZERO_STRUCT(hive_hnd);
2830         ZERO_STRUCT(key_hnd);
2831
2832         result = winreg_printer_openkey(tmp_ctx,
2833                                         server_info,
2834                                         &winreg_pipe,
2835                                         path,
2836                                         key,
2837                                         false,
2838                                         access_mask,
2839                                         &hive_hnd,
2840                                         &key_hnd);
2841         if (!W_ERROR_IS_OK(result)) {
2842                 DEBUG(0, ("winreg_delete_printer_dataex: Could not open key %s: %s\n",
2843                           key, win_errstr(result)));
2844                 goto done;
2845         }
2846
2847         wvalue.name = value;
2848         status = rpccli_winreg_DeleteValue(winreg_pipe,
2849                                            tmp_ctx,
2850                                            &key_hnd,
2851                                            wvalue,
2852                                            &result);
2853         if (!NT_STATUS_IS_OK(status)) {
2854                 DEBUG(0, ("winreg_delete_printer_dataex: Could not delete value %s: %s\n",
2855                           value, nt_errstr(status)));
2856                 if (!W_ERROR_IS_OK(result)) {
2857                         goto done;
2858                 }
2859                 result = ntstatus_to_werror(status);
2860                 goto done;
2861         }
2862
2863         result = WERR_OK;
2864 done:
2865         if (winreg_pipe != NULL) {
2866                 if (is_valid_policy_hnd(&key_hnd)) {
2867                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2868                 }
2869                 if (is_valid_policy_hnd(&hive_hnd)) {
2870                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2871                 }
2872         }
2873
2874         TALLOC_FREE(tmp_ctx);
2875         return result;
2876 }
2877
2878 /* Enumerate on the subkeys of a given key and provide the data. */
2879 WERROR winreg_enum_printer_key(TALLOC_CTX *mem_ctx,
2880                                struct auth_serversupplied_info *server_info,
2881                                const char *printer,
2882                                const char *key,
2883                                uint32_t *pnum_subkeys,
2884                                const char ***psubkeys)
2885 {
2886         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2887         struct rpc_pipe_client *winreg_pipe = NULL;
2888         struct policy_handle hive_hnd, key_hnd;
2889         char *path;
2890         const char **subkeys = NULL;
2891         uint32_t num_subkeys = -1;
2892
2893         WERROR result = WERR_OK;
2894
2895         TALLOC_CTX *tmp_ctx;
2896
2897         tmp_ctx = talloc_new(mem_ctx);
2898         if (tmp_ctx == NULL) {
2899                 return WERR_NOMEM;
2900         }
2901
2902         path = winreg_printer_data_keyname(tmp_ctx, printer);
2903         if (path == NULL) {
2904                 TALLOC_FREE(tmp_ctx);
2905                 return WERR_NOMEM;
2906         }
2907
2908         ZERO_STRUCT(hive_hnd);
2909         ZERO_STRUCT(key_hnd);
2910
2911         result = winreg_printer_openkey(tmp_ctx,
2912                                         server_info,
2913                                         &winreg_pipe,
2914                                         path,
2915                                         key,
2916                                         false,
2917                                         access_mask,
2918                                         &hive_hnd,
2919                                         &key_hnd);
2920         if (!W_ERROR_IS_OK(result)) {
2921                 DEBUG(0, ("winreg_enum_printer_key: Could not open key %s: %s\n",
2922                           key, win_errstr(result)));
2923                 goto done;
2924         }
2925
2926         result = winreg_printer_enumkeys(tmp_ctx,
2927                                          winreg_pipe,
2928                                          &key_hnd,
2929                                          &num_subkeys,
2930                                          &subkeys);
2931         if (!W_ERROR_IS_OK(result)) {
2932                 DEBUG(0, ("winreg_enum_printer_key: Could not enumerate subkeys in %s: %s\n",
2933                           key, win_errstr(result)));
2934                 goto done;
2935         }
2936
2937         *pnum_subkeys = num_subkeys;
2938         if (psubkeys) {
2939                 *psubkeys = talloc_move(mem_ctx, &subkeys);
2940         }
2941
2942         result = WERR_OK;
2943 done:
2944         if (winreg_pipe != NULL) {
2945                 if (is_valid_policy_hnd(&key_hnd)) {
2946                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
2947                 }
2948                 if (is_valid_policy_hnd(&hive_hnd)) {
2949                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
2950                 }
2951         }
2952
2953         TALLOC_FREE(tmp_ctx);
2954         return result;
2955 }
2956
2957 /* Delete a key with subkeys of a given printer. */
2958 WERROR winreg_delete_printer_key(TALLOC_CTX *mem_ctx,
2959                                  struct auth_serversupplied_info *server_info,
2960                                  const char *printer,
2961                                  const char *key)
2962 {
2963         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2964         struct rpc_pipe_client *winreg_pipe = NULL;
2965         struct policy_handle hive_hnd, key_hnd;
2966         char *keyname;
2967         char *path;
2968         WERROR result;
2969         TALLOC_CTX *tmp_ctx;
2970
2971         tmp_ctx = talloc_new(mem_ctx);
2972         if (tmp_ctx == NULL) {
2973                 return WERR_NOMEM;
2974         }
2975
2976         path = winreg_printer_data_keyname(tmp_ctx, printer);
2977         if (path == NULL) {
2978                 TALLOC_FREE(tmp_ctx);
2979                 return WERR_NOMEM;
2980         }
2981
2982         result = winreg_printer_openkey(tmp_ctx,
2983                                         server_info,
2984                                         &winreg_pipe,
2985                                         path,
2986                                         key,
2987                                         false,
2988                                         access_mask,
2989                                         &hive_hnd,
2990                                         &key_hnd);
2991         if (!W_ERROR_IS_OK(result)) {
2992                 /* key doesn't exist */
2993                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2994                         result = WERR_OK;
2995                         goto done;
2996                 }
2997
2998                 DEBUG(0, ("winreg_delete_printer_key: Could not open key %s: %s\n",
2999                           key, win_errstr(result)));
3000                 goto done;
3001         }
3002
3003         if (is_valid_policy_hnd(&key_hnd)) {
3004                 rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3005         }
3006
3007         if (key == NULL || key[0] == '\0') {
3008                 keyname = path;
3009         } else {
3010                 keyname = talloc_asprintf(tmp_ctx,
3011                                           "%s\\%s",
3012                                           path,
3013                                           key);
3014                 if (keyname == NULL) {
3015                         result = WERR_NOMEM;
3016                         goto done;
3017                 }
3018         }
3019
3020         result = winreg_printer_delete_subkeys(tmp_ctx,
3021                                                winreg_pipe,
3022                                                &hive_hnd,
3023                                                access_mask,
3024                                                keyname);
3025         if (!W_ERROR_IS_OK(result)) {
3026                 DEBUG(0, ("winreg_delete_printer_key: Could not delete key %s: %s\n",
3027                           key, win_errstr(result)));
3028                 goto done;
3029         }
3030
3031 done:
3032         if (winreg_pipe != NULL) {
3033                 if (is_valid_policy_hnd(&key_hnd)) {
3034                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3035                 }
3036                 if (is_valid_policy_hnd(&hive_hnd)) {
3037                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
3038                 }
3039         }
3040
3041         TALLOC_FREE(tmp_ctx);
3042         return result;
3043 }
3044
3045 WERROR winreg_printer_update_changeid(TALLOC_CTX *mem_ctx,
3046                                       struct auth_serversupplied_info *server_info,
3047                                       const char *printer)
3048 {
3049         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3050         struct rpc_pipe_client *winreg_pipe = NULL;
3051         struct policy_handle hive_hnd, key_hnd;
3052         char *path;
3053         WERROR result;
3054         TALLOC_CTX *tmp_ctx;
3055
3056         tmp_ctx = talloc_new(mem_ctx);
3057         if (tmp_ctx == NULL) {
3058                 return WERR_NOMEM;
3059         }
3060
3061         path = winreg_printer_data_keyname(tmp_ctx, printer);
3062         if (path == NULL) {
3063                 TALLOC_FREE(tmp_ctx);
3064                 return WERR_NOMEM;
3065         }
3066
3067         ZERO_STRUCT(hive_hnd);
3068         ZERO_STRUCT(key_hnd);
3069
3070         result = winreg_printer_openkey(tmp_ctx,
3071                                         server_info,
3072                                         &winreg_pipe,
3073                                         path,
3074                                         "",
3075                                         false,
3076                                         access_mask,
3077                                         &hive_hnd,
3078                                         &key_hnd);
3079         if (!W_ERROR_IS_OK(result)) {
3080                 DEBUG(0, ("winreg_printer_update_changeid: Could not open key %s: %s\n",
3081                           path, win_errstr(result)));
3082                 goto done;
3083         }
3084
3085         result = winreg_printer_write_dword(tmp_ctx,
3086                                             winreg_pipe,
3087                                             &key_hnd,
3088                                             "ChangeID",
3089                                             winreg_printer_rev_changeid());
3090         if (!W_ERROR_IS_OK(result)) {
3091                 goto done;
3092         }
3093
3094         result = WERR_OK;
3095 done:
3096         if (winreg_pipe != NULL) {
3097                 if (is_valid_policy_hnd(&key_hnd)) {
3098                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3099                 }
3100                 if (is_valid_policy_hnd(&hive_hnd)) {
3101                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
3102                 }
3103         }
3104
3105         TALLOC_FREE(tmp_ctx);
3106         return result;
3107 }
3108
3109 WERROR winreg_printer_get_changeid(TALLOC_CTX *mem_ctx,
3110                                    struct auth_serversupplied_info *server_info,
3111                                    const char *printer,
3112                                    uint32_t *pchangeid)
3113 {
3114         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3115         struct rpc_pipe_client *winreg_pipe = NULL;
3116         struct policy_handle hive_hnd, key_hnd;
3117         uint32_t changeid = 0;
3118         char *path;
3119         WERROR result;
3120         TALLOC_CTX *tmp_ctx;
3121
3122         tmp_ctx = talloc_new(mem_ctx);
3123         if (tmp_ctx == NULL) {
3124                 return WERR_NOMEM;
3125         }
3126
3127         path = winreg_printer_data_keyname(tmp_ctx, printer);
3128         if (path == NULL) {
3129                 TALLOC_FREE(tmp_ctx);
3130                 return WERR_NOMEM;
3131         }
3132
3133         ZERO_STRUCT(hive_hnd);
3134         ZERO_STRUCT(key_hnd);
3135
3136         result = winreg_printer_openkey(tmp_ctx,
3137                                         server_info,
3138                                         &winreg_pipe,
3139                                         path,
3140                                         "",
3141                                         false,
3142                                         access_mask,
3143                                         &hive_hnd,
3144                                         &key_hnd);
3145         if (!W_ERROR_IS_OK(result)) {
3146                 DEBUG(0, ("winreg_printer_get_changeid: Could not open key %s: %s\n",
3147                           path, win_errstr(result)));
3148                 goto done;
3149         }
3150
3151         DEBUG(0, ("winreg_printer_get_changeid: get changeid from %s\n", path));
3152         result = winreg_printer_query_dword(tmp_ctx,
3153                                             winreg_pipe,
3154                                             &key_hnd,
3155                                             "ChangeID",
3156                                             &changeid);
3157         if (!W_ERROR_IS_OK(result)) {
3158                 goto done;
3159         }
3160
3161         if (pchangeid) {
3162                 *pchangeid = changeid;
3163         }
3164
3165         result = WERR_OK;
3166 done:
3167         if (winreg_pipe != NULL) {
3168                 if (is_valid_policy_hnd(&key_hnd)) {
3169                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL);
3170                 }
3171                 if (is_valid_policy_hnd(&hive_hnd)) {
3172                         rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL);
3173                 }
3174         }
3175
3176         TALLOC_FREE(tmp_ctx);
3177         return result;
3178 }
3179
3180 /*
3181  * The special behaviour of the spoolss forms is documented at the website:
3182  *
3183  * Managing Win32 Printserver Forms
3184  * http://unixwiz.net/techtips/winspooler-forms.html
3185  */
3186
3187 WERROR winreg_printer_addform1(TALLOC_CTX *mem_ctx,
3188                                struct auth_serversupplied_info *server_info,
3189                                struct spoolss_AddFormInfo1 *form)
3190 {
3191         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3192         struct rpc_pipe_client *winreg_pipe = NULL;
3193         struct policy_handle hive_hnd, key_hnd;
3194         struct winreg_String wvalue;
3195         DATA_BLOB blob;
3196         uint32_t num_info = 0;
3197         union spoolss_FormInfo *info = NULL;
3198         uint32_t i;
3199         WERROR result;
3200         NTSTATUS status;
3201         TALLOC_CTX *tmp_ctx;
3202
3203         tmp_ctx = talloc_new(mem_ctx);
3204         if (tmp_ctx == NULL) {
3205                 return WERR_NOMEM;
3206         }
3207
3208         ZERO_STRUCT(hive_hnd);
3209         ZERO_STRUCT(key_hnd);
3210
3211         result = winreg_printer_openkey(tmp_ctx,
3212                                         server_info,
3213                                         &winreg_pipe,
3214                                         TOP_LEVEL_CONTROL_FORMS_KEY,
3215                                         "",
3216                                         true,
3217                                         access_mask,
3218                                         &hive_hnd,
3219                                         &key_hnd);
3220         if (!W_ERROR_IS_OK(result)) {
3221                 DEBUG(0, ("winreg_printer_addform1: Could not open key %s: %s\n",
3222                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3223                 goto done;
3224         }
3225
3226         result = winreg_printer_enumforms1(tmp_ctx, server_info, &num_info, &info);
3227         if (!W_ERROR_IS_OK(result)) {
3228                 DEBUG(0, ("winreg_printer_addform: Could not enum keys %s: %s\n",
3229                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3230                 goto done;
3231         }
3232
3233         /* If form name already exists or is builtin return ALREADY_EXISTS */
3234         for (i = 0; i < num_info; i++) {
3235                 if (strequal(info[i].info1.form_name, form->form_name)) {
3236                         result = WERR_FILE_EXISTS;
3237                         goto done;
3238                 }
3239         }
3240
3241         wvalue.name = form->form_name;
3242
3243         blob = data_blob_talloc(tmp_ctx, NULL, 32);
3244         SIVAL(blob.data,  0, form->size.width);
3245         SIVAL(blob.data,  4, form->size.height);
3246         SIVAL(blob.data,  8, form->area.left);
3247         SIVAL(blob.data, 12, form->area.top);
3248         SIVAL(blob.data, 16, form->area.right);
3249         SIVAL(blob.data, 20, form->area.bottom);
3250         SIVAL(blob.data, 24, num_info + 1); /* FIXME */
3251         SIVAL(blob.data, 28, form->flags);
3252
3253         status = rpccli_winreg_SetValue(winreg_pipe,
3254                                         tmp_ctx,
3255                                         &key_hnd,
3256                                         wvalue,
3257                                         REG_BINARY,
3258                                         blob.data,
3259                                         blob.length,
3260                                         &result);
3261         if (!NT_STATUS_IS_OK(status)) {
3262                 DEBUG(0, ("winreg_printer_addform1: Could not set value %s: %s\n",
3263                           wvalue.name, nt_errstr(status)));
3264                 if (!W_ERROR_IS_OK(result)) {
3265                         goto done;
3266                 }
3267                 result = ntstatus_to_werror(status);