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