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