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