b901d9640720b06d1693e4aaae89b02d8083e501
[kai/samba.git] / source3 / rpc_server / srv_spoolss_util.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *
4  *  SPOOLSS RPC Pipe server / winreg client routines
5  *
6  *  Copyright (c) 2010      Andreas Schneider <asn@samba.org>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "nt_printing.h"
24 #include "srv_spoolss_util.h"
25 #include "../librpc/gen_ndr/ndr_spoolss.h"
26 #include "../librpc/gen_ndr/srv_winreg.h"
27 #include "../librpc/gen_ndr/cli_winreg.h"
28 #include "../librpc/gen_ndr/ndr_security.h"
29 #include "secrets.h"
30 #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 *sharename)
1344 {
1345         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1346         struct dcerpc_binding_handle *winreg_handle = NULL;
1347         struct policy_handle hive_hnd, key_hnd;
1348         struct spoolss_SetPrinterInfo2 *info2;
1349         struct security_descriptor *secdesc;
1350         struct winreg_String wkey, wkeyclass;
1351         const char *path;
1352         const char *subkeys[] = { SPOOL_DSDRIVER_KEY, SPOOL_DSSPOOLER_KEY, SPOOL_PRINTERDATA_KEY };
1353         uint32_t i, count = ARRAY_SIZE(subkeys);
1354         uint32_t info2_mask = 0;
1355         WERROR result = WERR_OK;
1356         TALLOC_CTX *tmp_ctx;
1357
1358         tmp_ctx = talloc_stackframe();
1359         if (tmp_ctx == NULL) {
1360                 return WERR_NOMEM;
1361         }
1362
1363         path = winreg_printer_data_keyname(tmp_ctx, sharename);
1364         if (path == NULL) {
1365                 TALLOC_FREE(tmp_ctx);
1366                 return WERR_NOMEM;
1367         }
1368
1369         ZERO_STRUCT(hive_hnd);
1370         ZERO_STRUCT(key_hnd);
1371
1372         result = winreg_printer_openkey(tmp_ctx,
1373                                         server_info,
1374                                         msg_ctx,
1375                                         &winreg_handle,
1376                                         path,
1377                                         "",
1378                                         false,
1379                                         access_mask,
1380                                         &hive_hnd,
1381                                         &key_hnd);
1382         if (W_ERROR_IS_OK(result)) {
1383                 DEBUG(2, ("winreg_create_printer: Skipping, %s already exists\n", path));
1384                 goto done;
1385         } else if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1386                 DEBUG(2, ("winreg_create_printer: Creating default values in %s\n", path));
1387         } else if (!W_ERROR_IS_OK(result)) {
1388                 DEBUG(0, ("winreg_create_printer: Could not open key %s: %s\n",
1389                         path, win_errstr(result)));
1390                 goto done;
1391         }
1392
1393         /* Create the main key */
1394         result = winreg_printer_openkey(tmp_ctx,
1395                                         server_info,
1396                                         msg_ctx,
1397                                         &winreg_handle,
1398                                         path,
1399                                         "",
1400                                         true,
1401                                         access_mask,
1402                                         &hive_hnd,
1403                                         &key_hnd);
1404         if (!W_ERROR_IS_OK(result)) {
1405                 DEBUG(0, ("winreg_create_printer_keys: Could not create key %s: %s\n",
1406                         path, win_errstr(result)));
1407                 goto done;
1408         }
1409
1410         if (is_valid_policy_hnd(&key_hnd)) {
1411                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &result);
1412         }
1413
1414         /* Create subkeys */
1415         for (i = 0; i < count; i++) {
1416                 NTSTATUS status;
1417                 enum winreg_CreateAction action = REG_ACTION_NONE;
1418
1419                 ZERO_STRUCT(key_hnd);
1420                 ZERO_STRUCT(wkey);
1421
1422                 wkey.name = talloc_asprintf(tmp_ctx, "%s\\%s", path, subkeys[i]);
1423                 if (wkey.name == NULL) {
1424                         result = WERR_NOMEM;
1425                         goto done;
1426                 }
1427
1428                 ZERO_STRUCT(wkeyclass);
1429                 wkeyclass.name = "";
1430
1431                 status = dcerpc_winreg_CreateKey(winreg_handle,
1432                                                  tmp_ctx,
1433                                                  &hive_hnd,
1434                                                  wkey,
1435                                                  wkeyclass,
1436                                                  0,
1437                                                  access_mask,
1438                                                  NULL,
1439                                                  &key_hnd,
1440                                                  &action,
1441                                                  &result);
1442                 if (!NT_STATUS_IS_OK(status)) {
1443                         result = ntstatus_to_werror(status);
1444                 }
1445                 if (!W_ERROR_IS_OK(result)) {
1446                         DEBUG(0, ("winreg_create_printer_keys: Could not create key %s: %s\n",
1447                                 wkey.name, win_errstr(result)));
1448                         goto done;
1449                 }
1450
1451                 switch (i) {
1452                 case 1: {
1453                         const char *dnssuffix;
1454                         const char *longname;
1455                         const char *uncname;
1456
1457                         result = winreg_printer_write_sz(tmp_ctx,
1458                                                          winreg_handle,
1459                                                          &key_hnd,
1460                                                          SPOOL_REG_PRINTERNAME,
1461                                                          sharename);
1462                         if (!W_ERROR_IS_OK(result)) {
1463                                 goto done;
1464                         }
1465
1466                         result = winreg_printer_write_sz(tmp_ctx,
1467                                                          winreg_handle,
1468                                                          &key_hnd,
1469                                                          SPOOL_REG_SHORTSERVERNAME,
1470                                                          global_myname());
1471                         if (!W_ERROR_IS_OK(result)) {
1472                                 goto done;
1473                         }
1474
1475                         /* We make the assumption that the netbios name
1476                          * is the same as the DNS name since the former
1477                          * will be what we used to join the domain
1478                          */
1479                         dnssuffix = get_mydnsdomname(tmp_ctx);
1480                         if (dnssuffix != NULL && dnssuffix[0] != '\0') {
1481                                 longname = talloc_asprintf(tmp_ctx, "%s.%s", global_myname(), dnssuffix);
1482                         } else {
1483                                 longname = talloc_strdup(tmp_ctx, global_myname());
1484                         }
1485                         if (longname == NULL) {
1486                                 result = WERR_NOMEM;
1487                                 goto done;
1488                         }
1489
1490                         result = winreg_printer_write_sz(tmp_ctx,
1491                                                          winreg_handle,
1492                                                          &key_hnd,
1493                                                          SPOOL_REG_SERVERNAME,
1494                                                          longname);
1495                         if (!W_ERROR_IS_OK(result)) {
1496                                 goto done;
1497                         }
1498
1499                         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
1500                                                   longname, sharename);
1501                         if (uncname == NULL) {
1502                                 result = WERR_NOMEM;
1503                                 goto done;
1504                         }
1505
1506                         result = winreg_printer_write_sz(tmp_ctx,
1507                                                          winreg_handle,
1508                                                          &key_hnd,
1509                                                          SPOOL_REG_UNCNAME,
1510                                                          uncname);
1511                         if (!W_ERROR_IS_OK(result)) {
1512                                 goto done;
1513                         }
1514
1515                         result = winreg_printer_write_dword(tmp_ctx,
1516                                                             winreg_handle,
1517                                                             &key_hnd,
1518                                                             SPOOL_REG_VERSIONNUMBER,
1519                                                             4);
1520                         if (!W_ERROR_IS_OK(result)) {
1521                                 goto done;
1522                         }
1523
1524                         result = winreg_printer_write_dword(tmp_ctx,
1525                                                             winreg_handle,
1526                                                             &key_hnd,
1527                                                             SPOOL_REG_PRINTSTARTTIME,
1528                                                             0);
1529                         if (!W_ERROR_IS_OK(result)) {
1530                                 goto done;
1531                         }
1532
1533                         result = winreg_printer_write_dword(tmp_ctx,
1534                                                             winreg_handle,
1535                                                             &key_hnd,
1536                                                             SPOOL_REG_PRINTENDTIME,
1537                                                             0);
1538                         if (!W_ERROR_IS_OK(result)) {
1539                                 goto done;
1540                         }
1541
1542                         result = winreg_printer_write_dword(tmp_ctx,
1543                                                             winreg_handle,
1544                                                             &key_hnd,
1545                                                             SPOOL_REG_PRIORITY,
1546                                                             1);
1547                         if (!W_ERROR_IS_OK(result)) {
1548                                 goto done;
1549                         }
1550
1551                         result = winreg_printer_write_dword(tmp_ctx,
1552                                                             winreg_handle,
1553                                                             &key_hnd,
1554                                                             SPOOL_REG_PRINTKEEPPRINTEDJOBS,
1555                                                             0);
1556                         if (!W_ERROR_IS_OK(result)) {
1557                                 goto done;
1558                         }
1559                 } /* case 1 */
1560                 default:
1561                         break;
1562                 }
1563
1564                 if (is_valid_policy_hnd(&key_hnd)) {
1565                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &result);
1566                 }
1567         }
1568         info2 = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
1569         if (info2 == NULL) {
1570                 result = WERR_NOMEM;
1571                 goto done;
1572         }
1573
1574         info2->printername = sharename;
1575         if (info2->printername == NULL) {
1576                 result = WERR_NOMEM;
1577                 goto done;
1578         }
1579         info2_mask |= SPOOLSS_PRINTER_INFO_PRINTERNAME;
1580
1581         info2->sharename = sharename;
1582         info2_mask |= SPOOLSS_PRINTER_INFO_SHARENAME;
1583
1584         info2->portname = SAMBA_PRINTER_PORT_NAME;
1585         info2_mask |= SPOOLSS_PRINTER_INFO_PORTNAME;
1586
1587         info2->printprocessor = "winprint";
1588         info2_mask |= SPOOLSS_PRINTER_INFO_PRINTPROCESSOR;
1589
1590         info2->datatype = "RAW";
1591         info2_mask |= SPOOLSS_PRINTER_INFO_DATATYPE;
1592
1593         info2->comment = "";
1594         info2_mask |= SPOOLSS_PRINTER_INFO_COMMENT;
1595
1596         info2->attributes = PRINTER_ATTRIBUTE_SAMBA;
1597         info2_mask |= SPOOLSS_PRINTER_INFO_ATTRIBUTES;
1598
1599         info2->starttime = 0; /* Minutes since 12:00am GMT */
1600         info2_mask |= SPOOLSS_PRINTER_INFO_STARTTIME;
1601
1602         info2->untiltime = 0; /* Minutes since 12:00am GMT */
1603         info2_mask |= SPOOLSS_PRINTER_INFO_UNTILTIME;
1604
1605         info2->priority = 1;
1606         info2_mask |= SPOOLSS_PRINTER_INFO_PRIORITY;
1607
1608         info2->defaultpriority = 1;
1609         info2_mask |= SPOOLSS_PRINTER_INFO_DEFAULTPRIORITY;
1610
1611         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
1612         if (!W_ERROR_IS_OK(result)) {
1613                 goto done;
1614         }
1615         info2_mask |= SPOOLSS_PRINTER_INFO_SECDESC;
1616
1617         /*
1618          * Don't write a default Device Mode to the registry! The Device Mode is
1619          * only written to disk with a SetPrinter level 2 or 8.
1620          */
1621
1622         result = winreg_update_printer(tmp_ctx,
1623                                        server_info,
1624                                        msg_ctx,
1625                                        sharename,
1626                                        info2_mask,
1627                                        info2,
1628                                        NULL,
1629                                        secdesc);
1630
1631 done:
1632         if (winreg_handle != NULL) {
1633                 WERROR ignore;
1634
1635                 if (is_valid_policy_hnd(&key_hnd)) {
1636                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1637                 }
1638                 if (is_valid_policy_hnd(&hive_hnd)) {
1639                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1640                 }
1641         }
1642
1643         talloc_free(tmp_ctx);
1644         return result;
1645 }
1646
1647 WERROR winreg_update_printer(TALLOC_CTX *mem_ctx,
1648                              const struct auth_serversupplied_info *server_info,
1649                              struct messaging_context *msg_ctx,
1650                              const char *sharename,
1651                              uint32_t info2_mask,
1652                              struct spoolss_SetPrinterInfo2 *info2,
1653                              struct spoolss_DeviceMode *devmode,
1654                              struct security_descriptor *secdesc)
1655 {
1656         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1657         struct dcerpc_binding_handle *winreg_handle = NULL;
1658         struct policy_handle hive_hnd, key_hnd;
1659         int snum = lp_servicenumber(sharename);
1660         enum ndr_err_code ndr_err;
1661         DATA_BLOB blob;
1662         char *path;
1663         WERROR result = WERR_OK;
1664         TALLOC_CTX *tmp_ctx;
1665
1666         tmp_ctx = talloc_stackframe();
1667         if (tmp_ctx == NULL) {
1668                 return WERR_NOMEM;
1669         }
1670
1671         path = winreg_printer_data_keyname(tmp_ctx, sharename);
1672         if (path == NULL) {
1673                 TALLOC_FREE(tmp_ctx);
1674                 return WERR_NOMEM;
1675         }
1676
1677         ZERO_STRUCT(hive_hnd);
1678         ZERO_STRUCT(key_hnd);
1679
1680         result = winreg_printer_openkey(tmp_ctx,
1681                                         server_info,
1682                                         msg_ctx,
1683                                         &winreg_handle,
1684                                         path,
1685                                         "",
1686                                         true,
1687                                         access_mask,
1688                                         &hive_hnd,
1689                                         &key_hnd);
1690         if (!W_ERROR_IS_OK(result)) {
1691                 DEBUG(0, ("winreg_update_printer: Could not open key %s: %s\n",
1692                         path, win_errstr(result)));
1693                 goto done;
1694         }
1695
1696         if (info2_mask & SPOOLSS_PRINTER_INFO_ATTRIBUTES) {
1697                 result = winreg_printer_write_dword(tmp_ctx,
1698                                                     winreg_handle,
1699                                                     &key_hnd,
1700                                                     "Attributes",
1701                                                     info2->attributes);
1702                 if (!W_ERROR_IS_OK(result)) {
1703                         goto done;
1704                 }
1705         }
1706
1707 #if 0
1708         if (info2_mask & SPOOLSS_PRINTER_INFO_AVERAGEPPM) {
1709                 result = winreg_printer_write_dword(tmp_ctx,
1710                                                     winreg_handle,
1711                                                     &key_hnd,
1712                                                     "AveragePpm",
1713                                                     info2->attributes);
1714                 if (!W_ERROR_IS_OK(result)) {
1715                         goto done;
1716                 }
1717         }
1718 #endif
1719
1720         if (info2_mask & SPOOLSS_PRINTER_INFO_COMMENT) {
1721                 result = winreg_printer_write_sz(tmp_ctx,
1722                                                  winreg_handle,
1723                                                  &key_hnd,
1724                                                  "Description",
1725                                                  info2->comment);
1726                 if (!W_ERROR_IS_OK(result)) {
1727                         goto done;
1728                 }
1729         }
1730
1731         if (info2_mask & SPOOLSS_PRINTER_INFO_DATATYPE) {
1732                 result = winreg_printer_write_sz(tmp_ctx,
1733                                                  winreg_handle,
1734                                                  &key_hnd,
1735                                                  "Datatype",
1736                                                  info2->datatype);
1737                 if (!W_ERROR_IS_OK(result)) {
1738                         goto done;
1739                 }
1740         }
1741
1742         if (info2_mask & SPOOLSS_PRINTER_INFO_DEFAULTPRIORITY) {
1743                 result = winreg_printer_write_dword(tmp_ctx,
1744                                                     winreg_handle,
1745                                                     &key_hnd,
1746                                                     "Default Priority",
1747                                                     info2->defaultpriority);
1748                 if (!W_ERROR_IS_OK(result)) {
1749                         goto done;
1750                 }
1751         }
1752
1753         if (info2_mask & SPOOLSS_PRINTER_INFO_DEVMODE) {
1754                 /*
1755                  * Some client drivers freak out if there is a NULL devmode
1756                  * (probably the driver is not checking before accessing
1757                  * the devmode pointer)   --jerry
1758                  */
1759                 if (devmode == NULL && lp_default_devmode(snum) && info2 != NULL) {
1760                         result = spoolss_create_default_devmode(tmp_ctx,
1761                                                                 info2->printername,
1762                                                                 &devmode);
1763                         if (!W_ERROR_IS_OK(result)) {
1764                                 goto done;
1765                         }
1766                 }
1767                 ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, devmode,
1768                                 (ndr_push_flags_fn_t) ndr_push_spoolss_DeviceMode);
1769                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1770                         DEBUG(0, ("winreg_update_printer: Failed to marshall device mode\n"));
1771                         result = WERR_NOMEM;
1772                         goto done;
1773                 }
1774
1775                 result = winreg_printer_write_binary(tmp_ctx,
1776                                                      winreg_handle,
1777                                                      &key_hnd,
1778                                                      "Default DevMode",
1779                                                      blob);
1780                 if (!W_ERROR_IS_OK(result)) {
1781                         goto done;
1782                 }
1783         }
1784
1785         if (info2_mask & SPOOLSS_PRINTER_INFO_DRIVERNAME) {
1786                 result = winreg_printer_write_sz(tmp_ctx,
1787                                                  winreg_handle,
1788                                                  &key_hnd,
1789                                                  "Printer Driver",
1790                                                  info2->drivername);
1791                 if (!W_ERROR_IS_OK(result)) {
1792                         goto done;
1793                 }
1794         }
1795
1796         if (info2_mask & SPOOLSS_PRINTER_INFO_LOCATION) {
1797                 result = winreg_printer_write_sz(tmp_ctx,
1798                                                  winreg_handle,
1799                                                  &key_hnd,
1800                                                  "Location",
1801                                                  info2->location);
1802                 if (!W_ERROR_IS_OK(result)) {
1803                         goto done;
1804                 }
1805         }
1806
1807         if (info2_mask & SPOOLSS_PRINTER_INFO_PARAMETERS) {
1808                 result = winreg_printer_write_sz(tmp_ctx,
1809                                                  winreg_handle,
1810                                                  &key_hnd,
1811                                                  "Parameters",
1812                                                  info2->parameters);
1813                 if (!W_ERROR_IS_OK(result)) {
1814                         goto done;
1815                 }
1816         }
1817
1818         if (info2_mask & SPOOLSS_PRINTER_INFO_PORTNAME) {
1819                 result = winreg_printer_write_sz(tmp_ctx,
1820                                                  winreg_handle,
1821                                                  &key_hnd,
1822                                                  "Port",
1823                                                  info2->portname);
1824                 if (!W_ERROR_IS_OK(result)) {
1825                         goto done;
1826                 }
1827         }
1828
1829         if (info2_mask & SPOOLSS_PRINTER_INFO_PRINTERNAME) {
1830                 /*
1831                  * in addprinter: no servername and the printer is the name
1832                  * in setprinter: servername is \\server
1833                  *                and printer is \\server\\printer
1834                  *
1835                  * Samba manages only local printers.
1836                  * we currently don't support things like i
1837                  * path=\\other_server\printer
1838                  *
1839                  * We only store the printername, not \\server\printername
1840                  */
1841                 const char *p = strrchr(info2->printername, '\\');
1842                 if (p == NULL) {
1843                         p = info2->printername;
1844                 } else {
1845                         p++;
1846                 }
1847                 result = winreg_printer_write_sz(tmp_ctx,
1848                                                  winreg_handle,
1849                                                  &key_hnd,
1850                                                  "Name",
1851                                                  p);
1852                 if (!W_ERROR_IS_OK(result)) {
1853                         goto done;
1854                 }
1855         }
1856
1857         if (info2_mask & SPOOLSS_PRINTER_INFO_PRINTPROCESSOR) {
1858                 result = winreg_printer_write_sz(tmp_ctx,
1859                                                  winreg_handle,
1860                                                  &key_hnd,
1861                                                  "Print Processor",
1862                                                  info2->printprocessor);
1863                 if (!W_ERROR_IS_OK(result)) {
1864                         goto done;
1865                 }
1866         }
1867
1868         if (info2_mask & SPOOLSS_PRINTER_INFO_PRIORITY) {
1869                 result = winreg_printer_write_dword(tmp_ctx,
1870                                                     winreg_handle,
1871                                                     &key_hnd,
1872                                                     "Priority",
1873                                                     info2->priority);
1874                 if (!W_ERROR_IS_OK(result)) {
1875                         goto done;
1876                 }
1877         }
1878
1879         if (info2_mask & SPOOLSS_PRINTER_INFO_SECDESC) {
1880                 /*
1881                  * We need a security descriptor, if it isn't specified by
1882                  * AddPrinter{Ex} then create a default descriptor.
1883                  */
1884                 if (secdesc == NULL) {
1885                         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
1886                         if (!W_ERROR_IS_OK(result)) {
1887                                 goto done;
1888                         }
1889                 }
1890                 result = winreg_set_printer_secdesc(tmp_ctx,
1891                                                     server_info,
1892                                                     msg_ctx,
1893                                                     sharename,
1894                                                     secdesc);
1895                 if (!W_ERROR_IS_OK(result)) {
1896                         goto done;
1897                 }
1898         }
1899
1900         if (info2_mask & SPOOLSS_PRINTER_INFO_SEPFILE) {
1901                 result = winreg_printer_write_sz(tmp_ctx,
1902                                                  winreg_handle,
1903                                                  &key_hnd,
1904                                                  "Separator File",
1905                                                  info2->sepfile);
1906                 if (!W_ERROR_IS_OK(result)) {
1907                         goto done;
1908                 }
1909         }
1910
1911         if (info2_mask & SPOOLSS_PRINTER_INFO_SHARENAME) {
1912                 result = winreg_printer_write_sz(tmp_ctx,
1913                                                  winreg_handle,
1914                                                  &key_hnd,
1915                                                  "Share Name",
1916                                                  info2->sharename);
1917                 if (!W_ERROR_IS_OK(result)) {
1918                         goto done;
1919                 }
1920         }
1921
1922         if (info2_mask & SPOOLSS_PRINTER_INFO_STARTTIME) {
1923                 result = winreg_printer_write_dword(tmp_ctx,
1924                                                     winreg_handle,
1925                                                     &key_hnd,
1926                                                     "StartTime",
1927                                                     info2->starttime);
1928                 if (!W_ERROR_IS_OK(result)) {
1929                         goto done;
1930                 }
1931         }
1932
1933         if (info2_mask & SPOOLSS_PRINTER_INFO_STATUS) {
1934                 result = winreg_printer_write_dword(tmp_ctx,
1935                                                     winreg_handle,
1936                                                     &key_hnd,
1937                                                     "Status",
1938                                                     info2->status);
1939                 if (!W_ERROR_IS_OK(result)) {
1940                         goto done;
1941                 }
1942         }
1943
1944         if (info2_mask & SPOOLSS_PRINTER_INFO_UNTILTIME) {
1945                 result = winreg_printer_write_dword(tmp_ctx,
1946                                                     winreg_handle,
1947                                                     &key_hnd,
1948                                                     "UntilTime",
1949                                                     info2->untiltime);
1950                 if (!W_ERROR_IS_OK(result)) {
1951                         goto done;
1952                 }
1953         }
1954
1955         result = winreg_printer_write_dword(tmp_ctx,
1956                                             winreg_handle,
1957                                             &key_hnd,
1958                                             "ChangeID",
1959                                             winreg_printer_rev_changeid());
1960         if (!W_ERROR_IS_OK(result)) {
1961                 goto done;
1962         }
1963
1964         result = WERR_OK;
1965 done:
1966         if (winreg_handle != NULL) {
1967                 WERROR ignore;
1968
1969                 if (is_valid_policy_hnd(&key_hnd)) {
1970                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1971                 }
1972                 if (is_valid_policy_hnd(&hive_hnd)) {
1973                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1974                 }
1975         }
1976
1977         TALLOC_FREE(tmp_ctx);
1978         return result;
1979 }
1980
1981 WERROR winreg_get_printer(TALLOC_CTX *mem_ctx,
1982                           const struct auth_serversupplied_info *server_info,
1983                           struct messaging_context *msg_ctx,
1984                           const char *printer,
1985                           struct spoolss_PrinterInfo2 **pinfo2)
1986 {
1987         struct spoolss_PrinterInfo2 *info2;
1988         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1989         struct dcerpc_binding_handle *winreg_handle = NULL;
1990         struct policy_handle hive_hnd, key_hnd;
1991         struct spoolss_PrinterEnumValues *enum_values = NULL;
1992         struct spoolss_PrinterEnumValues *v;
1993         enum ndr_err_code ndr_err;
1994         DATA_BLOB blob;
1995         int snum = lp_servicenumber(printer);
1996         uint32_t num_values = 0;
1997         uint32_t i;
1998         char *path;
1999         WERROR result = WERR_OK;
2000         TALLOC_CTX *tmp_ctx;
2001
2002         tmp_ctx = talloc_stackframe();
2003         if (tmp_ctx == NULL) {
2004                 return WERR_NOMEM;
2005         }
2006
2007         path = winreg_printer_data_keyname(tmp_ctx, printer);
2008         if (path == NULL) {
2009                 TALLOC_FREE(tmp_ctx);
2010                 return WERR_NOMEM;
2011         }
2012
2013         result = winreg_printer_openkey(tmp_ctx,
2014                                         server_info,
2015                                         msg_ctx,
2016                                         &winreg_handle,
2017                                         path,
2018                                         "",
2019                                         false,
2020                                         access_mask,
2021                                         &hive_hnd,
2022                                         &key_hnd);
2023         if (!W_ERROR_IS_OK(result)) {
2024                 DEBUG(2, ("winreg_get_printer: Could not open key %s: %s\n",
2025                           path, win_errstr(result)));
2026                 goto done;
2027         }
2028
2029         result = winreg_printer_enumvalues(tmp_ctx,
2030                                            winreg_handle,
2031                                            &key_hnd,
2032                                            &num_values,
2033                                            &enum_values);
2034         if (!W_ERROR_IS_OK(result)) {
2035                 DEBUG(0, ("winreg_get_printer: Could not enumerate values in %s: %s\n",
2036                           path, win_errstr(result)));
2037                 goto done;
2038         }
2039
2040         info2 = talloc_zero(tmp_ctx, struct spoolss_PrinterInfo2);
2041         if (info2 == NULL) {
2042                 result = WERR_NOMEM;
2043                 goto done;
2044         }
2045
2046         FILL_STRING(info2, EMPTY_STRING, info2->servername);
2047         FILL_STRING(info2, EMPTY_STRING, info2->printername);
2048         FILL_STRING(info2, EMPTY_STRING, info2->sharename);
2049         FILL_STRING(info2, EMPTY_STRING, info2->portname);
2050         FILL_STRING(info2, EMPTY_STRING, info2->drivername);
2051         FILL_STRING(info2, EMPTY_STRING, info2->comment);
2052         FILL_STRING(info2, EMPTY_STRING, info2->location);
2053         FILL_STRING(info2, EMPTY_STRING, info2->sepfile);
2054         FILL_STRING(info2, EMPTY_STRING, info2->printprocessor);
2055         FILL_STRING(info2, EMPTY_STRING, info2->datatype);
2056         FILL_STRING(info2, EMPTY_STRING, info2->parameters);
2057
2058         for (i = 0; i < num_values; i++) {
2059                 v = &enum_values[i];
2060
2061                 result = winreg_enumval_to_sz(info2,
2062                                               v,
2063                                               "Name",
2064                                               &info2->printername);
2065                 CHECK_ERROR(result);
2066
2067                 result = winreg_enumval_to_sz(info2,
2068                                               v,
2069                                               "Share Name",
2070                                               &info2->sharename);
2071                 CHECK_ERROR(result);
2072
2073                 result = winreg_enumval_to_sz(info2,
2074                                               v,
2075                                               "Port",
2076                                               &info2->portname);
2077                 CHECK_ERROR(result);
2078
2079                 result = winreg_enumval_to_sz(info2,
2080                                               v,
2081                                               "Description",
2082                                               &info2->comment);
2083                 CHECK_ERROR(result);
2084
2085                 result = winreg_enumval_to_sz(info2,
2086                                               v,
2087                                               "Location",
2088                                               &info2->location);
2089                 CHECK_ERROR(result);
2090
2091                 result = winreg_enumval_to_sz(info2,
2092                                               v,
2093                                               "Separator File",
2094                                               &info2->sepfile);
2095                 CHECK_ERROR(result);
2096
2097                 result = winreg_enumval_to_sz(info2,
2098                                               v,
2099                                               "Print Processor",
2100                                               &info2->printprocessor);
2101                 CHECK_ERROR(result);
2102
2103                 result = winreg_enumval_to_sz(info2,
2104                                               v,
2105                                               "Datatype",
2106                                               &info2->datatype);
2107                 CHECK_ERROR(result);
2108
2109                 result = winreg_enumval_to_sz(info2,
2110                                               v,
2111                                               "Parameters",
2112                                               &info2->parameters);
2113                 CHECK_ERROR(result);
2114
2115                 result = winreg_enumval_to_sz(info2,
2116                                               v,
2117                                               "Printer Driver",
2118                                               &info2->drivername);
2119                 CHECK_ERROR(result);
2120
2121                 result = winreg_enumval_to_dword(info2,
2122                                                  v,
2123                                                  "Attributes",
2124                                                  &info2->attributes);
2125                 CHECK_ERROR(result);
2126
2127                 result = winreg_enumval_to_dword(info2,
2128                                                  v,
2129                                                  "Priority",
2130                                                  &info2->priority);
2131                 CHECK_ERROR(result);
2132
2133                 result = winreg_enumval_to_dword(info2,
2134                                                  v,
2135                                                  "Default Priority",
2136                                                  &info2->defaultpriority);
2137                 CHECK_ERROR(result);
2138
2139                 result = winreg_enumval_to_dword(info2,
2140                                                  v,
2141                                                  "StartTime",
2142                                                  &info2->starttime);
2143                 CHECK_ERROR(result);
2144
2145                 result = winreg_enumval_to_dword(info2,
2146                                                  v,
2147                                                  "UntilTime",
2148                                                  &info2->untiltime);
2149                 CHECK_ERROR(result);
2150
2151                 result = winreg_enumval_to_dword(info2,
2152                                                  v,
2153                                                  "Status",
2154                                                  &info2->status);
2155                 CHECK_ERROR(result);
2156
2157                 result = winreg_enumval_to_dword(info2,
2158                                                  v,
2159                                                  "StartTime",
2160                                                  &info2->starttime);
2161                 CHECK_ERROR(result);
2162         }
2163
2164         if (!W_ERROR_IS_OK(result)) {
2165                 DEBUG(0, ("winreg_get_printer: winreg_enumval_to_TYPE() failed "
2166                                         "for %s: %s\n",
2167                                         v->value_name,
2168                                         win_errstr(result)));
2169                 goto done;
2170         }
2171
2172         /* Construct the Device Mode */
2173         result = winreg_printer_query_binary(tmp_ctx,
2174                                              winreg_handle,
2175                                              &key_hnd,
2176                                              "Default DevMode",
2177                                              &blob);
2178         if (W_ERROR_IS_OK(result)) {
2179                 info2->devmode = talloc_zero(info2, struct spoolss_DeviceMode);
2180                 if (info2->devmode == NULL) {
2181                         result = WERR_NOMEM;
2182                         goto done;
2183                 }
2184                 ndr_err = ndr_pull_struct_blob(&blob,
2185                                                info2->devmode,
2186                                                info2->devmode,
2187                                                (ndr_pull_flags_fn_t) ndr_pull_spoolss_DeviceMode);
2188                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2189                         DEBUG(0, ("winreg_get_printer: Failed to unmarshall device mode\n"));
2190                         result = WERR_NOMEM;
2191                         goto done;
2192                 }
2193         }
2194
2195         if (info2->devmode == NULL && lp_default_devmode(snum)) {
2196                 result = spoolss_create_default_devmode(info2,
2197                                                         info2->printername,
2198                                                         &info2->devmode);
2199                 if (!W_ERROR_IS_OK(result)) {
2200                         goto done;
2201                 }
2202         }
2203
2204         result = winreg_get_printer_secdesc(info2,
2205                                             server_info,
2206                                             msg_ctx,
2207                                             printer,
2208                                             &info2->secdesc);
2209         if (!W_ERROR_IS_OK(result)) {
2210                 goto done;
2211         }
2212
2213         /* Fix for OS/2 drivers. */
2214         if (get_remote_arch() == RA_OS2) {
2215                 spoolss_map_to_os2_driver(info2, &info2->drivername);
2216         }
2217
2218         if (pinfo2) {
2219                 *pinfo2 = talloc_move(mem_ctx, &info2);
2220         }
2221
2222         result = WERR_OK;
2223 done:
2224         if (winreg_handle != NULL) {
2225                 WERROR ignore;
2226
2227                 if (is_valid_policy_hnd(&key_hnd)) {
2228                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2229                 }
2230                 if (is_valid_policy_hnd(&hive_hnd)) {
2231                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2232                 }
2233         }
2234
2235         TALLOC_FREE(tmp_ctx);
2236         return result;
2237 }
2238
2239 WERROR winreg_get_printer_secdesc(TALLOC_CTX *mem_ctx,
2240                                   const struct auth_serversupplied_info *server_info,
2241                                   struct messaging_context *msg_ctx,
2242                                   const char *sharename,
2243                                   struct spoolss_security_descriptor **psecdesc)
2244 {
2245         struct spoolss_security_descriptor *secdesc;
2246         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2247         struct dcerpc_binding_handle *winreg_handle = NULL;
2248         struct policy_handle hive_hnd, key_hnd;
2249         enum ndr_err_code ndr_err;
2250         const char *path;
2251         DATA_BLOB blob;
2252         TALLOC_CTX *tmp_ctx;
2253         WERROR result;
2254
2255         tmp_ctx = talloc_stackframe();
2256         if (tmp_ctx == NULL) {
2257                 return WERR_NOMEM;
2258         }
2259
2260         path = winreg_printer_data_keyname(tmp_ctx, sharename);
2261         if (path == NULL) {
2262                 talloc_free(tmp_ctx);
2263                 return WERR_NOMEM;
2264         }
2265
2266         ZERO_STRUCT(hive_hnd);
2267         ZERO_STRUCT(key_hnd);
2268
2269         result = winreg_printer_openkey(tmp_ctx,
2270                                         server_info,
2271                                         msg_ctx,
2272                                         &winreg_handle,
2273                                         path,
2274                                         "",
2275                                         false,
2276                                         access_mask,
2277                                         &hive_hnd,
2278                                         &key_hnd);
2279         if (!W_ERROR_IS_OK(result)) {
2280                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2281                         goto create_default;
2282                 }
2283                 goto done;
2284         }
2285
2286         result = winreg_printer_query_binary(tmp_ctx,
2287                                              winreg_handle,
2288                                              &key_hnd,
2289                                              "Security",
2290                                              &blob);
2291         if (!W_ERROR_IS_OK(result)) {
2292                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2293                         goto create_default;
2294                 }
2295                 goto done;
2296         }
2297
2298         secdesc = talloc_zero(tmp_ctx, struct spoolss_security_descriptor);
2299         if (secdesc == NULL) {
2300                 result = WERR_NOMEM;
2301                 goto done;
2302         }
2303         ndr_err = ndr_pull_struct_blob(&blob,
2304                                        secdesc,
2305                                        secdesc,
2306                                        (ndr_pull_flags_fn_t) ndr_pull_security_descriptor);
2307         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2308                 DEBUG(0, ("winreg_get_secdesc: Failed to unmarshall security descriptor\n"));
2309                 result = WERR_NOMEM;
2310                 goto done;
2311         }
2312
2313         if (psecdesc) {
2314                 *psecdesc = talloc_move(mem_ctx, &secdesc);
2315         }
2316
2317         result = WERR_OK;
2318         goto done;
2319
2320 create_default:
2321         result = winreg_printer_openkey(tmp_ctx,
2322                                         server_info,
2323                                         msg_ctx,
2324                                         &winreg_handle,
2325                                         path,
2326                                         "",
2327                                         true,
2328                                         access_mask,
2329                                         &hive_hnd,
2330                                         &key_hnd);
2331         if (!W_ERROR_IS_OK(result)) {
2332                 goto done;
2333         }
2334
2335         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
2336         if (!W_ERROR_IS_OK(result)) {
2337                 goto done;
2338         }
2339
2340         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
2341            this security descriptor has been created when winbindd was
2342            down.  Take ownership of security descriptor. */
2343         if (dom_sid_equal(secdesc->owner_sid, &global_sid_World)) {
2344                 struct dom_sid owner_sid;
2345
2346                 /* Change sd owner to workgroup administrator */
2347
2348                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
2349                         struct spoolss_security_descriptor *new_secdesc;
2350                         size_t size;
2351
2352                         /* Create new sd */
2353                         sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
2354
2355                         new_secdesc = make_sec_desc(tmp_ctx,
2356                                                     secdesc->revision,
2357                                                     secdesc->type,
2358                                                     &owner_sid,
2359                                                     secdesc->group_sid,
2360                                                     secdesc->sacl,
2361                                                     secdesc->dacl,
2362                                                     &size);
2363
2364                         if (new_secdesc == NULL) {
2365                                 result = WERR_NOMEM;
2366                                 goto done;
2367                         }
2368
2369                         /* Swap with other one */
2370                         secdesc = new_secdesc;
2371                 }
2372         }
2373
2374         ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, secdesc,
2375                         (ndr_push_flags_fn_t) ndr_push_security_descriptor);
2376         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2377                 DEBUG(0, ("winreg_set_secdesc: Failed to marshall security descriptor\n"));
2378                 result = WERR_NOMEM;
2379                 goto done;
2380         }
2381
2382         result = winreg_printer_write_binary(tmp_ctx,
2383                                              winreg_handle,
2384                                              &key_hnd,
2385                                              "Security",
2386                                              blob);
2387         if (!W_ERROR_IS_OK(result)) {
2388                 return result;
2389         }
2390
2391         if (psecdesc) {
2392                 *psecdesc = talloc_move(mem_ctx, &secdesc);
2393         }
2394
2395         result = WERR_OK;
2396 done:
2397         if (winreg_handle != NULL) {
2398                 WERROR ignore;
2399
2400                 if (is_valid_policy_hnd(&key_hnd)) {
2401                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2402                 }
2403                 if (is_valid_policy_hnd(&hive_hnd)) {
2404                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2405                 }
2406         }
2407
2408         talloc_free(tmp_ctx);
2409         return result;
2410 }
2411
2412 WERROR winreg_set_printer_secdesc(TALLOC_CTX *mem_ctx,
2413                                   const struct auth_serversupplied_info *server_info,
2414                                   struct messaging_context *msg_ctx,
2415                                   const char *sharename,
2416                                   const struct spoolss_security_descriptor *secdesc)
2417 {
2418         const struct spoolss_security_descriptor *new_secdesc = secdesc;
2419         struct spoolss_security_descriptor *old_secdesc;
2420         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2421         struct dcerpc_binding_handle *winreg_handle = NULL;
2422         struct policy_handle hive_hnd, key_hnd;
2423         enum ndr_err_code ndr_err;
2424         const char *path;
2425         DATA_BLOB blob;
2426         TALLOC_CTX *tmp_ctx;
2427         WERROR result;
2428
2429         tmp_ctx = talloc_stackframe();
2430         if (tmp_ctx == NULL) {
2431                 return WERR_NOMEM;
2432         }
2433
2434         path = winreg_printer_data_keyname(tmp_ctx, sharename);
2435         if (path == NULL) {
2436                 talloc_free(tmp_ctx);
2437                 return WERR_NOMEM;
2438         }
2439
2440         /*
2441          * The old owner and group sids of the security descriptor are not
2442          * present when new ACEs are added or removed by changing printer
2443          * permissions through NT.  If they are NULL in the new security
2444          * descriptor then copy them over from the old one.
2445          */
2446         if (!secdesc->owner_sid || !secdesc->group_sid) {
2447                 struct dom_sid *owner_sid, *group_sid;
2448                 struct security_acl *dacl, *sacl;
2449                 size_t size;
2450
2451                 result = winreg_get_printer_secdesc(tmp_ctx,
2452                                                     server_info,
2453                                                     msg_ctx,
2454                                                     sharename,
2455                                                     &old_secdesc);
2456                 if (!W_ERROR_IS_OK(result)) {
2457                         talloc_free(tmp_ctx);
2458                         return result;
2459                 }
2460
2461                 /* Pick out correct owner and group sids */
2462                 owner_sid = secdesc->owner_sid ?
2463                             secdesc->owner_sid :
2464                             old_secdesc->owner_sid;
2465
2466                 group_sid = secdesc->group_sid ?
2467                             secdesc->group_sid :
2468                             old_secdesc->group_sid;
2469
2470                 dacl = secdesc->dacl ?
2471                        secdesc->dacl :
2472                        old_secdesc->dacl;
2473
2474                 sacl = secdesc->sacl ?
2475                        secdesc->sacl :
2476                        old_secdesc->sacl;
2477
2478                 /* Make a deep copy of the security descriptor */
2479                 new_secdesc = make_sec_desc(tmp_ctx,
2480                                             secdesc->revision,
2481                                             secdesc->type,
2482                                             owner_sid,
2483                                             group_sid,
2484                                             sacl,
2485                                             dacl,
2486                                             &size);
2487                 if (new_secdesc == NULL) {
2488                         talloc_free(tmp_ctx);
2489                         return WERR_NOMEM;
2490                 }
2491         }
2492
2493         ZERO_STRUCT(hive_hnd);
2494         ZERO_STRUCT(key_hnd);
2495
2496         result = winreg_printer_openkey(tmp_ctx,
2497                                         server_info,
2498                                         msg_ctx,
2499                                         &winreg_handle,
2500                                         path,
2501                                         "",
2502                                         false,
2503                                         access_mask,
2504                                         &hive_hnd,
2505                                         &key_hnd);
2506         if (!W_ERROR_IS_OK(result)) {
2507                 goto done;
2508         }
2509
2510         ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, new_secdesc,
2511                         (ndr_push_flags_fn_t) ndr_push_security_descriptor);
2512         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2513                 DEBUG(0, ("winreg_set_secdesc: Failed to marshall security descriptor\n"));
2514                 result = WERR_NOMEM;
2515                 goto done;
2516         }
2517
2518         result = winreg_printer_write_binary(tmp_ctx,
2519                                              winreg_handle,
2520                                              &key_hnd,
2521                                              "Security",
2522                                              blob);
2523
2524 done:
2525         if (winreg_handle != NULL) {
2526                 WERROR ignore;
2527
2528                 if (is_valid_policy_hnd(&key_hnd)) {
2529                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2530                 }
2531                 if (is_valid_policy_hnd(&hive_hnd)) {
2532                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2533                 }
2534         }
2535
2536         talloc_free(tmp_ctx);
2537         return result;
2538 }
2539
2540 /* Set printer data over the winreg pipe. */
2541 WERROR winreg_set_printer_dataex(TALLOC_CTX *mem_ctx,
2542                                  const struct auth_serversupplied_info *server_info,
2543                                  struct messaging_context *msg_ctx,
2544                                  const char *printer,
2545                                  const char *key,
2546                                  const char *value,
2547                                  enum winreg_Type type,
2548                                  uint8_t *data,
2549                                  uint32_t data_size)
2550 {
2551         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2552         struct dcerpc_binding_handle *winreg_handle = NULL;
2553         struct policy_handle hive_hnd, key_hnd;
2554         struct winreg_String wvalue;
2555         char *path;
2556         WERROR result = WERR_OK;
2557         NTSTATUS status;
2558         TALLOC_CTX *tmp_ctx;
2559
2560         tmp_ctx = talloc_stackframe();
2561         if (tmp_ctx == NULL) {
2562                 return WERR_NOMEM;
2563         }
2564
2565         path = winreg_printer_data_keyname(tmp_ctx, printer);
2566         if (path == NULL) {
2567                 TALLOC_FREE(tmp_ctx);
2568                 return WERR_NOMEM;
2569         }
2570
2571         ZERO_STRUCT(hive_hnd);
2572         ZERO_STRUCT(key_hnd);
2573
2574         DEBUG(8, ("winreg_set_printer_dataex: Open printer key %s, value %s, access_mask: 0x%05x for [%s]\n",
2575                         key, value, access_mask, printer));
2576         result = winreg_printer_openkey(tmp_ctx,
2577                                         server_info,
2578                                         msg_ctx,
2579                                         &winreg_handle,
2580                                         path,
2581                                         key,
2582                                         true,
2583                                         access_mask,
2584                                         &hive_hnd,
2585                                         &key_hnd);
2586         if (!W_ERROR_IS_OK(result)) {
2587                 DEBUG(0, ("winreg_set_printer_dataex: Could not open key %s: %s\n",
2588                           key, win_errstr(result)));
2589                 goto done;
2590         }
2591
2592         wvalue.name = value;
2593         status = dcerpc_winreg_SetValue(winreg_handle,
2594                                         tmp_ctx,
2595                                         &key_hnd,
2596                                         wvalue,
2597                                         type,
2598                                         data,
2599                                         data_size,
2600                                         &result);
2601         if (!NT_STATUS_IS_OK(status)) {
2602                 DEBUG(0, ("winreg_set_printer_dataex: Could not set value %s: %s\n",
2603                           value, nt_errstr(status)));
2604                 result = ntstatus_to_werror(status);
2605         }
2606
2607 done:
2608         if (winreg_handle != NULL) {
2609                 WERROR ignore;
2610
2611                 if (is_valid_policy_hnd(&key_hnd)) {
2612                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2613                 }
2614                 if (is_valid_policy_hnd(&hive_hnd)) {
2615                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2616                 }
2617         }
2618
2619         TALLOC_FREE(tmp_ctx);
2620         return result;
2621 }
2622
2623 /* Get printer data over a winreg pipe. */
2624 WERROR winreg_get_printer_dataex(TALLOC_CTX *mem_ctx,
2625                                  const struct auth_serversupplied_info *server_info,
2626                                  struct messaging_context *msg_ctx,
2627                                  const char *printer,
2628                                  const char *key,
2629                                  const char *value,
2630                                  enum winreg_Type *type,
2631                                  uint8_t **data,
2632                                  uint32_t *data_size)
2633 {
2634         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2635         struct dcerpc_binding_handle *winreg_handle = NULL;
2636         struct policy_handle hive_hnd, key_hnd;
2637         struct winreg_String wvalue;
2638         enum winreg_Type type_in;
2639         char *path;
2640         uint8_t *data_in;
2641         uint32_t data_in_size = 0;
2642         uint32_t value_len = 0;
2643         WERROR result = WERR_OK;
2644         NTSTATUS status;
2645         TALLOC_CTX *tmp_ctx;
2646
2647         tmp_ctx = talloc_stackframe();
2648         if (tmp_ctx == NULL) {
2649                 return WERR_NOMEM;
2650         }
2651
2652         path = winreg_printer_data_keyname(tmp_ctx, printer);
2653         if (path == NULL) {
2654                 TALLOC_FREE(tmp_ctx);
2655                 return WERR_NOMEM;
2656         }
2657
2658         ZERO_STRUCT(hive_hnd);
2659         ZERO_STRUCT(key_hnd);
2660
2661         result = winreg_printer_openkey(tmp_ctx,
2662                                         server_info,
2663                                         msg_ctx,
2664                                         &winreg_handle,
2665                                         path,
2666                                         key,
2667                                         false,
2668                                         access_mask,
2669                                         &hive_hnd,
2670                                         &key_hnd);
2671         if (!W_ERROR_IS_OK(result)) {
2672                 DEBUG(2, ("winreg_get_printer_dataex: Could not open key %s: %s\n",
2673                           key, win_errstr(result)));
2674                 goto done;
2675         }
2676
2677         wvalue.name = value;
2678
2679         /*
2680          * call QueryValue once with data == NULL to get the
2681          * needed memory size to be allocated, then allocate
2682          * data buffer and call again.
2683          */
2684         status = dcerpc_winreg_QueryValue(winreg_handle,
2685                                           tmp_ctx,
2686                                           &key_hnd,
2687                                           &wvalue,
2688                                           &type_in,
2689                                           NULL,
2690                                           &data_in_size,
2691                                           &value_len,
2692                                           &result);
2693         if (!NT_STATUS_IS_OK(status)) {
2694                 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2695                           value, nt_errstr(status)));
2696                 result = ntstatus_to_werror(status);
2697                 goto done;
2698         }
2699         if (!W_ERROR_IS_OK(result)) {
2700                 goto done;
2701         }
2702
2703         data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
2704         if (data_in == NULL) {
2705                 result = WERR_NOMEM;
2706                 goto done;
2707         }
2708         value_len = 0;
2709
2710         status = dcerpc_winreg_QueryValue(winreg_handle,
2711                                           tmp_ctx,
2712                                           &key_hnd,
2713                                           &wvalue,
2714                                           &type_in,
2715                                           data_in,
2716                                           &data_in_size,
2717                                           &value_len,
2718                                           &result);
2719         if (!NT_STATUS_IS_OK(status)) {
2720                 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2721                           value, nt_errstr(status)));
2722                 result = ntstatus_to_werror(status);
2723                 goto done;
2724         }
2725         if (!W_ERROR_IS_OK(result)) {
2726                 goto done;
2727         }
2728
2729         *type = type_in;
2730         *data_size = data_in_size;
2731         if (data_in_size) {
2732                 *data = talloc_move(mem_ctx, &data_in);
2733         }
2734
2735         result = WERR_OK;
2736 done:
2737         if (winreg_handle != NULL) {
2738                 WERROR ignore;
2739
2740                 if (is_valid_policy_hnd(&key_hnd)) {
2741                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2742                 }
2743                 if (is_valid_policy_hnd(&hive_hnd)) {
2744                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2745                 }
2746         }
2747
2748         TALLOC_FREE(tmp_ctx);
2749         return result;
2750 }
2751
2752 /* Enumerate on the values of a given key and provide the data. */
2753 WERROR winreg_enum_printer_dataex(TALLOC_CTX *mem_ctx,
2754                                   const struct auth_serversupplied_info *server_info,
2755                                   struct messaging_context *msg_ctx,
2756                                   const char *printer,
2757                                   const char *key,
2758                                   uint32_t *pnum_values,
2759                                   struct spoolss_PrinterEnumValues **penum_values)
2760 {
2761         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2762         struct dcerpc_binding_handle *winreg_handle = NULL;
2763         struct policy_handle hive_hnd, key_hnd;
2764
2765         struct spoolss_PrinterEnumValues *enum_values = NULL;
2766         uint32_t num_values = 0;
2767         char *path;
2768         WERROR result = WERR_OK;
2769
2770         TALLOC_CTX *tmp_ctx;
2771
2772         tmp_ctx = talloc_stackframe();
2773         if (tmp_ctx == NULL) {
2774                 return WERR_NOMEM;
2775         }
2776
2777         path = winreg_printer_data_keyname(tmp_ctx, printer);
2778         if (path == NULL) {
2779                 TALLOC_FREE(tmp_ctx);
2780                 return WERR_NOMEM;
2781         }
2782
2783         result = winreg_printer_openkey(tmp_ctx,
2784                                         server_info,
2785                                         msg_ctx,
2786                                         &winreg_handle,
2787                                         path,
2788                                         key,
2789                                         false,
2790                                         access_mask,
2791                                         &hive_hnd,
2792                                         &key_hnd);
2793         if (!W_ERROR_IS_OK(result)) {
2794                 DEBUG(2, ("winreg_enum_printer_dataex: Could not open key %s: %s\n",
2795                           key, win_errstr(result)));
2796                 goto done;
2797         }
2798
2799         result = winreg_printer_enumvalues(tmp_ctx,
2800                                            winreg_handle,
2801                                            &key_hnd,
2802                                            &num_values,
2803                                            &enum_values);
2804         if (!W_ERROR_IS_OK(result)) {
2805                 DEBUG(0, ("winreg_enum_printer_dataex: Could not enumerate values in %s: %s\n",
2806                           key, win_errstr(result)));
2807                 goto done;
2808         }
2809
2810         *pnum_values = num_values;
2811         if (penum_values) {
2812                 *penum_values = talloc_move(mem_ctx, &enum_values);
2813         }
2814
2815         result = WERR_OK;
2816 done:
2817         if (winreg_handle != NULL) {
2818                 WERROR ignore;
2819
2820                 if (is_valid_policy_hnd(&key_hnd)) {
2821                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2822                 }
2823                 if (is_valid_policy_hnd(&hive_hnd)) {
2824                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2825                 }
2826         }
2827
2828         TALLOC_FREE(tmp_ctx);
2829         return result;
2830 }
2831
2832 /* Delete printer data over a winreg pipe. */
2833 WERROR winreg_delete_printer_dataex(TALLOC_CTX *mem_ctx,
2834                                     const struct auth_serversupplied_info *server_info,
2835                                     struct messaging_context *msg_ctx,
2836                                     const char *printer,
2837                                     const char *key,
2838                                     const char *value)
2839 {
2840         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2841         struct dcerpc_binding_handle *winreg_handle = NULL;
2842         struct policy_handle hive_hnd, key_hnd;
2843         struct winreg_String wvalue;
2844         char *path;
2845         WERROR result = WERR_OK;
2846         NTSTATUS status;
2847
2848         TALLOC_CTX *tmp_ctx;
2849
2850         tmp_ctx = talloc_stackframe();
2851         if (tmp_ctx == NULL) {
2852                 return WERR_NOMEM;
2853         }
2854
2855         path = winreg_printer_data_keyname(tmp_ctx, printer);
2856         if (path == NULL) {
2857                 TALLOC_FREE(tmp_ctx);
2858                 return WERR_NOMEM;
2859         }
2860
2861         ZERO_STRUCT(hive_hnd);
2862         ZERO_STRUCT(key_hnd);
2863
2864         result = winreg_printer_openkey(tmp_ctx,
2865                                         server_info,
2866                                         msg_ctx,
2867                                         &winreg_handle,
2868                                         path,
2869                                         key,
2870                                         false,
2871                                         access_mask,
2872                                         &hive_hnd,
2873                                         &key_hnd);
2874         if (!W_ERROR_IS_OK(result)) {
2875                 DEBUG(0, ("winreg_delete_printer_dataex: Could not open key %s: %s\n",
2876                           key, win_errstr(result)));
2877                 goto done;
2878         }
2879
2880         wvalue.name = value;
2881         status = dcerpc_winreg_DeleteValue(winreg_handle,
2882                                            tmp_ctx,
2883                                            &key_hnd,
2884                                            wvalue,
2885                                            &result);
2886         if (!NT_STATUS_IS_OK(status)) {
2887                 DEBUG(0, ("winreg_delete_printer_dataex: Could not delete value %s: %s\n",
2888                           value, nt_errstr(status)));
2889                 result = ntstatus_to_werror(status);
2890         }
2891
2892 done:
2893         if (winreg_handle != NULL) {
2894                 WERROR ignore;
2895
2896                 if (is_valid_policy_hnd(&key_hnd)) {
2897                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2898                 }
2899                 if (is_valid_policy_hnd(&hive_hnd)) {
2900                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2901                 }
2902         }
2903
2904         TALLOC_FREE(tmp_ctx);
2905         return result;
2906 }
2907
2908 /* Enumerate on the subkeys of a given key and provide the data. */
2909 WERROR winreg_enum_printer_key(TALLOC_CTX *mem_ctx,
2910                                const struct auth_serversupplied_info *server_info,
2911                                struct messaging_context *msg_ctx,
2912                                const char *printer,
2913                                const char *key,
2914                                uint32_t *pnum_subkeys,
2915                                const char ***psubkeys)
2916 {
2917         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2918         struct dcerpc_binding_handle *winreg_handle = NULL;
2919         struct policy_handle hive_hnd, key_hnd;
2920         char *path;
2921         const char **subkeys = NULL;
2922         uint32_t num_subkeys = -1;
2923
2924         WERROR result = WERR_OK;
2925
2926         TALLOC_CTX *tmp_ctx;
2927
2928         tmp_ctx = talloc_stackframe();
2929         if (tmp_ctx == NULL) {
2930                 return WERR_NOMEM;
2931         }
2932
2933         path = winreg_printer_data_keyname(tmp_ctx, printer);
2934         if (path == NULL) {
2935                 TALLOC_FREE(tmp_ctx);
2936                 return WERR_NOMEM;
2937         }
2938
2939         ZERO_STRUCT(hive_hnd);
2940         ZERO_STRUCT(key_hnd);
2941
2942         result = winreg_printer_openkey(tmp_ctx,
2943                                         server_info,
2944                                         msg_ctx,
2945                                         &winreg_handle,
2946                                         path,
2947                                         key,
2948                                         false,
2949                                         access_mask,
2950                                         &hive_hnd,
2951                                         &key_hnd);
2952         if (!W_ERROR_IS_OK(result)) {
2953                 DEBUG(2, ("winreg_enum_printer_key: Could not open key %s: %s\n",
2954                           key, win_errstr(result)));
2955                 goto done;
2956         }
2957
2958         result = winreg_printer_enumkeys(tmp_ctx,
2959                                          winreg_handle,
2960                                          &key_hnd,
2961                                          &num_subkeys,
2962                                          &subkeys);
2963         if (!W_ERROR_IS_OK(result)) {
2964                 DEBUG(0, ("winreg_enum_printer_key: Could not enumerate subkeys in %s: %s\n",
2965                           key, win_errstr(result)));
2966                 goto done;
2967         }
2968
2969         *pnum_subkeys = num_subkeys;
2970         if (psubkeys) {
2971                 *psubkeys = talloc_move(mem_ctx, &subkeys);
2972         }
2973
2974         result = WERR_OK;
2975 done:
2976         if (winreg_handle != NULL) {
2977                 WERROR ignore;
2978
2979                 if (is_valid_policy_hnd(&key_hnd)) {
2980                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2981                 }
2982                 if (is_valid_policy_hnd(&hive_hnd)) {
2983                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2984                 }
2985         }
2986
2987         TALLOC_FREE(tmp_ctx);
2988         return result;
2989 }
2990
2991 /* Delete a key with subkeys of a given printer. */
2992 WERROR winreg_delete_printer_key(TALLOC_CTX *mem_ctx,
2993                                  const struct auth_serversupplied_info *server_info,
2994                                  struct messaging_context *msg_ctx,
2995                                  const char *printer,
2996                                  const char *key)
2997 {
2998         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2999         struct dcerpc_binding_handle *winreg_handle = NULL;
3000         struct policy_handle hive_hnd, key_hnd;
3001         char *keyname;
3002         char *path;
3003         WERROR result;
3004         TALLOC_CTX *tmp_ctx;
3005
3006         tmp_ctx = talloc_stackframe();
3007         if (tmp_ctx == NULL) {
3008                 return WERR_NOMEM;
3009         }
3010
3011         path = winreg_printer_data_keyname(tmp_ctx, printer);
3012         if (path == NULL) {
3013                 TALLOC_FREE(tmp_ctx);
3014                 return WERR_NOMEM;
3015         }
3016
3017         result = winreg_printer_openkey(tmp_ctx,
3018                                         server_info,
3019                                         msg_ctx,
3020                                         &winreg_handle,
3021                                         path,
3022                                         key,
3023                                         false,
3024                                         access_mask,
3025                                         &hive_hnd,
3026                                         &key_hnd);
3027         if (!W_ERROR_IS_OK(result)) {
3028                 /* key doesn't exist */
3029                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
3030                         result = WERR_OK;
3031                         goto done;
3032                 }
3033
3034                 DEBUG(0, ("winreg_delete_printer_key: Could not open key %s: %s\n",
3035                           key, win_errstr(result)));
3036                 goto done;
3037         }
3038
3039         if (is_valid_policy_hnd(&key_hnd)) {
3040                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &result);
3041         }
3042
3043         if (key == NULL || key[0] == '\0') {
3044                 keyname = path;
3045         } else {
3046                 keyname = talloc_asprintf(tmp_ctx,
3047                                           "%s\\%s",
3048                                           path,
3049                                           key);
3050                 if (keyname == NULL) {
3051                         result = WERR_NOMEM;
3052                         goto done;
3053                 }
3054         }
3055
3056         result = winreg_printer_delete_subkeys(tmp_ctx,
3057                                                winreg_handle,
3058                                                &hive_hnd,
3059                                                access_mask,
3060                                                keyname);
3061         if (!W_ERROR_IS_OK(result)) {
3062                 DEBUG(0, ("winreg_delete_printer_key: Could not delete key %s: %s\n",
3063                           key, win_errstr(result)));
3064                 goto done;
3065         }
3066
3067 done:
3068         if (winreg_handle != NULL) {
3069                 WERROR ignore;
3070
3071                 if (is_valid_policy_hnd(&key_hnd)) {
3072                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3073                 }
3074                 if (is_valid_policy_hnd(&hive_hnd)) {
3075                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3076                 }
3077         }
3078
3079         TALLOC_FREE(tmp_ctx);
3080         return result;
3081 }
3082
3083 WERROR winreg_printer_update_changeid(TALLOC_CTX *mem_ctx,
3084                                       const struct auth_serversupplied_info *server_info,
3085                                       struct messaging_context *msg_ctx,
3086                                       const char *printer)
3087 {
3088         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3089         struct dcerpc_binding_handle *winreg_handle = NULL;
3090         struct policy_handle hive_hnd, key_hnd;
3091         char *path;
3092         WERROR result;
3093         TALLOC_CTX *tmp_ctx;
3094
3095         tmp_ctx = talloc_stackframe();
3096         if (tmp_ctx == NULL) {
3097                 return WERR_NOMEM;
3098         }
3099
3100         path = winreg_printer_data_keyname(tmp_ctx, printer);
3101         if (path == NULL) {
3102                 TALLOC_FREE(tmp_ctx);
3103                 return WERR_NOMEM;
3104         }
3105
3106         ZERO_STRUCT(hive_hnd);
3107         ZERO_STRUCT(key_hnd);
3108
3109         result = winreg_printer_openkey(tmp_ctx,
3110                                         server_info,
3111                                         msg_ctx,
3112                                         &winreg_handle,
3113                                         path,
3114                                         "",
3115                                         false,
3116                                         access_mask,
3117                                         &hive_hnd,
3118                                         &key_hnd);
3119         if (!W_ERROR_IS_OK(result)) {
3120                 DEBUG(0, ("winreg_printer_update_changeid: Could not open key %s: %s\n",
3121                           path, win_errstr(result)));
3122                 goto done;
3123         }
3124
3125         result = winreg_printer_write_dword(tmp_ctx,
3126                                             winreg_handle,
3127                                             &key_hnd,
3128                                             "ChangeID",
3129                                             winreg_printer_rev_changeid());
3130         if (!W_ERROR_IS_OK(result)) {
3131                 goto done;
3132         }
3133
3134         result = WERR_OK;
3135 done:
3136         if (winreg_handle != NULL) {
3137                 WERROR ignore;
3138
3139                 if (is_valid_policy_hnd(&key_hnd)) {
3140                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3141                 }
3142                 if (is_valid_policy_hnd(&hive_hnd)) {
3143                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3144                 }
3145         }
3146
3147         TALLOC_FREE(tmp_ctx);
3148         return result;
3149 }
3150
3151 WERROR winreg_printer_get_changeid(TALLOC_CTX *mem_ctx,
3152                                    const struct auth_serversupplied_info *server_info,
3153                                    struct messaging_context *msg_ctx,
3154                                    const char *printer,
3155                                    uint32_t *pchangeid)
3156 {
3157         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3158         struct dcerpc_binding_handle *winreg_handle = NULL;
3159         struct policy_handle hive_hnd, key_hnd;
3160         uint32_t changeid = 0;
3161         char *path;
3162         WERROR result;
3163         TALLOC_CTX *tmp_ctx;
3164
3165         tmp_ctx = talloc_stackframe();
3166         if (tmp_ctx == NULL) {
3167                 return WERR_NOMEM;
3168         }
3169
3170         path = winreg_printer_data_keyname(tmp_ctx, printer);
3171         if (path == NULL) {
3172                 TALLOC_FREE(tmp_ctx);
3173                 return WERR_NOMEM;
3174         }
3175
3176         ZERO_STRUCT(hive_hnd);
3177         ZERO_STRUCT(key_hnd);
3178
3179         result = winreg_printer_openkey(tmp_ctx,
3180                                         server_info,
3181                                         msg_ctx,
3182                                         &winreg_handle,
3183                                         path,
3184                                         "",
3185                                         false,
3186                                         access_mask,
3187                                         &hive_hnd,
3188                                         &key_hnd);
3189         if (!W_ERROR_IS_OK(result)) {
3190                 DEBUG(2, ("winreg_printer_get_changeid: Could not open key %s: %s\n",
3191                           path, win_errstr(result)));
3192                 goto done;
3193         }
3194
3195         DEBUG(10, ("winreg_printer_get_changeid: get changeid from %s\n", path));
3196
3197         result = winreg_printer_query_dword(tmp_ctx,
3198                                             winreg_handle,
3199                                             &key_hnd,
3200                                             "ChangeID",
3201                                             &changeid);
3202         if (!W_ERROR_IS_OK(result)) {
3203                 goto done;
3204         }
3205
3206         if (pchangeid) {
3207                 *pchangeid = changeid;
3208         }
3209
3210         result = WERR_OK;
3211 done:
3212         if (winreg_handle != NULL) {
3213                 WERROR ignore;
3214
3215                 if (is_valid_policy_hnd(&key_hnd)) {
3216                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3217                 }
3218                 if (is_valid_policy_hnd(&hive_hnd)) {
3219                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3220                 }
3221         }
3222
3223         TALLOC_FREE(tmp_ctx);
3224         return result;
3225 }
3226
3227 /*
3228  * The special behaviour of the spoolss forms is documented at the website:
3229  *
3230  * Managing Win32 Printserver Forms
3231  * http://unixwiz.net/techtips/winspooler-forms.html
3232  */
3233
3234 WERROR winreg_printer_addform1(TALLOC_CTX *mem_ctx,
3235                                const struct auth_serversupplied_info *server_info,
3236                                struct messaging_context *msg_ctx,
3237                                struct spoolss_AddFormInfo1 *form)
3238 {
3239         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3240         struct dcerpc_binding_handle *winreg_handle = NULL;
3241         struct policy_handle hive_hnd, key_hnd;
3242         struct winreg_String wvalue;
3243         DATA_BLOB blob;
3244         uint32_t num_info = 0;
3245         union spoolss_FormInfo *info = NULL;
3246         uint32_t i;
3247         WERROR result;
3248         NTSTATUS status;
3249         TALLOC_CTX *tmp_ctx;
3250
3251         tmp_ctx = talloc_stackframe();
3252         if (tmp_ctx == NULL) {
3253                 return WERR_NOMEM;
3254         }
3255
3256         ZERO_STRUCT(hive_hnd);
3257         ZERO_STRUCT(key_hnd);
3258
3259         result = winreg_printer_openkey(tmp_ctx,
3260                                         server_info,
3261                                         msg_ctx,
3262                                         &winreg_handle,
3263                                         TOP_LEVEL_CONTROL_FORMS_KEY,
3264                                         "",
3265                                         true,
3266                                         access_mask,
3267                                         &hive_hnd,
3268                                         &key_hnd);
3269         if (!W_ERROR_IS_OK(result)) {
3270                 DEBUG(0, ("winreg_printer_addform1: Could not open key %s: %s\n",
3271                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3272                 goto done;
3273         }
3274
3275         result = winreg_printer_enumforms1(tmp_ctx, server_info, msg_ctx,
3276                                            &num_info, &info);
3277         if (!W_ERROR_IS_OK(result)) {
3278                 DEBUG(0, ("winreg_printer_addform: Could not enum keys %s: %s\n",
3279                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3280                 goto done;
3281         }
3282
3283         /* If form name already exists or is builtin return ALREADY_EXISTS */
3284         for (i = 0; i < num_info; i++) {
3285                 if (strequal(info[i].info1.form_name, form->form_name)) {
3286                         result = WERR_FILE_EXISTS;
3287                         goto done;
3288                 }
3289         }
3290
3291         wvalue.name = form->form_name;
3292
3293         blob = data_blob_talloc(tmp_ctx, NULL, 32);
3294         SIVAL(blob.data,  0, form->size.width);
3295         SIVAL(blob.data,  4, form->size.height);
3296         SIVAL(blob.data,  8, form->area.left);
3297         SIVAL(blob.data, 12, form->area.top);
3298         SIVAL(blob.data, 16, form->area.right);
3299         SIVAL(blob.data, 20, form->area.bottom);
3300         SIVAL(blob.data, 24, num_info + 1); /* FIXME */
3301         SIVAL(blob.data, 28, form->flags);
3302
3303         status = dcerpc_winreg_SetValue(winreg_handle,
3304                                         tmp_ctx,
3305                                         &key_hnd,
3306                                         wvalue,
3307                                         REG_BINARY,
3308                                         blob.data,
3309                                         blob.length,
3310                                         &result);
3311         if (!NT_STATUS_IS_OK(status)) {
3312                 DEBUG(0, ("winreg_printer_addform1: Could not set value %s: %s\n",
3313                           wvalue.name, nt_errstr(status)));
3314                 result = ntstatus_to_werror(status);
3315         }
3316
3317 done:
3318         if (winreg_handle != NULL) {
3319                 WERROR ignore;
3320
3321                 if (is_valid_policy_hnd(&key_hnd)) {
3322                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3323                 }
3324                 if (is_valid_policy_hnd(&hive_hnd)) {
3325                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3326                 }
3327         }
3328
3329         TALLOC_FREE(info);
3330         TALLOC_FREE(tmp_ctx);
3331         return result;
3332 }
3333
3334 WERROR winreg_printer_enumforms1(TALLOC_CTX *mem_ctx,
3335                                  const struct auth_serversupplied_info *server_info,
3336                                  struct messaging_context *msg_ctx,
3337                                  uint32_t *pnum_info,
3338                                  union spoolss_FormInfo **pinfo)
3339 {
3340         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3341         struct dcerpc_binding_handle *winreg_handle = NULL;
3342         struct policy_handle hive_hnd, key_hnd;
3343         union spoolss_FormInfo *info;
3344         struct spoolss_PrinterEnumValues *enum_values = NULL;
3345         uint32_t num_values = 0;
3346         uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
3347         uint32_t i;
3348         WERROR result;
3349         TALLOC_CTX *tmp_ctx;
3350
3351         tmp_ctx = talloc_stackframe();
3352         if (tmp_ctx == NULL) {
3353                 return WERR_NOMEM;
3354         }
3355
3356         ZERO_STRUCT(hive_hnd);
3357         ZERO_STRUCT(key_hnd);
3358
3359         result = winreg_printer_openkey(tmp_ctx,
3360                                         server_info,
3361                                         msg_ctx,
3362                                         &winreg_handle,
3363                                         TOP_LEVEL_CONTROL_FORMS_KEY,
3364                                         "",
3365                                         true,
3366                                         access_mask,
3367                                         &hive_hnd,
3368                                         &key_hnd);
3369         if (!W_ERROR_IS_OK(result)) {
3370                 /* key doesn't exist */
3371                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
3372                         result = WERR_OK;
3373                         goto done;
3374                 }
3375
3376                 DEBUG(0, ("winreg_printer_enumforms1: Could not open key %s: %s\n",
3377                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3378                 goto done;
3379         }
3380
3381         result = winreg_printer_enumvalues(tmp_ctx,
3382                                            winreg_handle,
3383                                            &key_hnd,
3384                                            &num_values,
3385                                            &enum_values);
3386         if (!W_ERROR_IS_OK(result)) {
3387                 DEBUG(0, ("winreg_printer_enumforms1: Could not enumerate values in %s: %s\n",
3388                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3389                 goto done;
3390         }
3391
3392         info = TALLOC_ARRAY(tmp_ctx, union spoolss_FormInfo, num_builtin + num_values);
3393         if (info == NULL) {
3394                 result = WERR_NOMEM;
3395                 goto done;
3396         }
3397
3398         /* Enumerate BUILTIN forms */
3399         for (i = 0; i < num_builtin; i++) {
3400                 info[i].info1 = builtin_forms1[i];
3401         }
3402
3403         /* Enumerate registry forms */
3404         for (i = 0; i < num_values; i++) {
3405                 union spoolss_FormInfo val;
3406
3407                 if (enum_values[i].type != REG_BINARY ||
3408                     enum_values[i].data_length != 32) {
3409                         continue;
3410                 }
3411
3412                 val.info1.form_name = talloc_strdup(info, enum_values[i].value_name);
3413                 if (val.info1.form_name == NULL) {
3414                         result = WERR_NOMEM;
3415                         goto done;
3416                 }
3417
3418                 val.info1.size.width  = IVAL(enum_values[i].data->data,  0);
3419                 val.info1.size.height = IVAL(enum_values[i].data->data,  4);
3420                 val.info1.area.left   = IVAL(enum_values[i].data->data,  8);
3421                 val.info1.area.top    = IVAL(enum_values[i].data->data, 12);
3422                 val.info1.area.right  = IVAL(enum_values[i].data->data, 16);
3423                 val.info1.area.bottom = IVAL(enum_values[i].data->data, 20);
3424                 /* skip form index      IVAL(enum_values[i].data->data, 24)));*/
3425                 val.info1.flags       = (enum spoolss_FormFlags) IVAL(enum_values[i].data->data, 28);
3426
3427                 info[i + num_builtin] = val;
3428         }
3429
3430         *pnum_info = num_builtin + num_values;
3431         if (pinfo) {
3432                 *pinfo = talloc_move(mem_ctx, &info);
3433         }
3434
3435 done:
3436         if (winreg_handle != NULL) {
3437                 WERROR ignore;
3438
3439                 if (is_valid_policy_hnd(&key_hnd)) {
3440                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3441                 }
3442                 if (is_valid_policy_hnd(&hive_hnd)) {
3443                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3444                 }
3445         }
3446
3447         TALLOC_FREE(enum_values);
3448         TALLOC_FREE(tmp_ctx);
3449         return result;
3450 }
3451
3452 WERROR winreg_printer_deleteform1(TALLOC_CTX *mem_ctx,
3453                                   const struct auth_serversupplied_info *server_info,
3454                                   struct messaging_context *msg_ctx,
3455                                   const char *form_name)
3456 {
3457         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3458         struct dcerpc_binding_handle *winreg_handle = NULL;
3459         struct policy_handle hive_hnd, key_hnd;
3460         struct winreg_String wvalue;
3461         uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
3462         uint32_t i;
3463         WERROR result = WERR_OK;
3464         NTSTATUS status;
3465         TALLOC_CTX *tmp_ctx;
3466
3467         for (i = 0; i < num_builtin; i++) {
3468                 if (strequal(builtin_forms1[i].form_name, form_name)) {
3469                         return WERR_INVALID_PARAMETER;
3470                 }
3471         }
3472
3473         tmp_ctx = talloc_stackframe();
3474         if (tmp_ctx == NULL) {
3475                 return WERR_NOMEM;
3476         }
3477
3478         ZERO_STRUCT(hive_hnd);
3479         ZERO_STRUCT(key_hnd);
3480
3481         result = winreg_printer_openkey(tmp_ctx,
3482                                         server_info,
3483                                         msg_ctx,
3484                                         &winreg_handle,
3485                                         TOP_LEVEL_CONTROL_FORMS_KEY,
3486                                         "",
3487                                         false,
3488                                         access_mask,
3489                                         &hive_hnd,
3490                                         &key_hnd);
3491         if (!W_ERROR_IS_OK(result)) {
3492                 DEBUG(0, ("winreg_printer_deleteform1: Could not open key %s: %s\n",
3493                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3494                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
3495                         result = WERR_INVALID_FORM_NAME;
3496                 }
3497                 goto done;
3498         }
3499
3500         wvalue.name = form_name;
3501         status = dcerpc_winreg_DeleteValue(winreg_handle,
3502                                            tmp_ctx,
3503                                            &key_hnd,
3504                                            wvalue,
3505                                            &result);
3506         if (!NT_STATUS_IS_OK(status)) {
3507                 /* If the value doesn't exist, return WERR_INVALID_FORM_NAME */
3508                 DEBUG(0, ("winreg_printer_delteform1: Could not delete value %s: %s\n",
3509                           wvalue.name, nt_errstr(status)));
3510                 result = ntstatus_to_werror(status);
3511                 goto done;
3512         }
3513
3514         if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
3515                 result = WERR_INVALID_FORM_NAME;
3516         }
3517
3518 done:
3519         if (winreg_handle != NULL) {
3520                 WERROR ignore;
3521
3522                 if (is_valid_policy_hnd(&key_hnd)) {
3523                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3524                 }
3525                 if (is_valid_policy_hnd(&hive_hnd)) {
3526                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3527                 }
3528         }
3529
3530         TALLOC_FREE(tmp_ctx);
3531         return result;
3532 }
3533
3534 WERROR winreg_printer_setform1(TALLOC_CTX *mem_ctx,
3535                                const struct auth_serversupplied_info *server_info,
3536                                struct messaging_context *msg_ctx,
3537                                const char *form_name,
3538                                struct spoolss_AddFormInfo1 *form)
3539 {
3540         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3541         struct dcerpc_binding_handle *winreg_handle = NULL;
3542         struct policy_handle hive_hnd, key_hnd;
3543         struct winreg_String wvalue;
3544         DATA_BLOB blob;
3545         uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
3546         uint32_t i;
3547         WERROR result;
3548         NTSTATUS status;
3549         TALLOC_CTX *tmp_ctx = NULL;
3550
3551         for (i = 0; i < num_builtin; i++) {
3552                 if (strequal(builtin_forms1[i].form_name, form->form_name)) {
3553                         result = WERR_INVALID_PARAM;
3554                         goto done;
3555                 }
3556         }
3557
3558         tmp_ctx = talloc_stackframe();
3559         if (tmp_ctx == NULL) {
3560                 return WERR_NOMEM;
3561         }
3562
3563         ZERO_STRUCT(hive_hnd);
3564         ZERO_STRUCT(key_hnd);
3565
3566         result = winreg_printer_openkey(tmp_ctx,
3567                                         server_info,
3568                                         msg_ctx,
3569                                         &winreg_handle,
3570                                         TOP_LEVEL_CONTROL_FORMS_KEY,
3571                                         "",
3572                                         true,
3573                                         access_mask,
3574                                         &hive_hnd,
3575                                         &key_hnd);
3576         if (!W_ERROR_IS_OK(result)) {
3577                 DEBUG(0, ("winreg_printer_setform1: Could not open key %s: %s\n",
3578                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3579                 goto done;
3580         }
3581
3582         /* If form_name != form->form_name then we renamed the form */
3583         if (strequal(form_name, form->form_name)) {
3584                 result = winreg_printer_deleteform1(tmp_ctx, server_info,
3585                                                     msg_ctx, form_name);
3586                 if (!W_ERROR_IS_OK(result)) {
3587                         DEBUG(0, ("winreg_printer_setform1: Could not open key %s: %s\n",
3588                                   TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3589                         goto done;
3590                 }
3591         }
3592
3593         wvalue.name = form->form_name;
3594
3595         blob = data_blob_talloc(tmp_ctx, NULL, 32);
3596         SIVAL(blob.data,  0, form->size.width);
3597         SIVAL(blob.data,  4, form->size.height);
3598         SIVAL(blob.data,  8, form->area.left);
3599         SIVAL(blob.data, 12, form->area.top);
3600         SIVAL(blob.data, 16, form->area.right);
3601         SIVAL(blob.data, 20, form->area.bottom);
3602         SIVAL(blob.data, 24, 42);
3603         SIVAL(blob.data, 28, form->flags);
3604
3605         status = dcerpc_winreg_SetValue(winreg_handle,
3606                                         tmp_ctx,
3607                                         &key_hnd,
3608                                         wvalue,
3609                                         REG_BINARY,
3610                                         blob.data,
3611                                         blob.length,
3612                                         &result);
3613         if (!NT_STATUS_IS_OK(status)) {
3614                 DEBUG(0, ("winreg_printer_setform1: Could not set value %s: %s\n",
3615                           wvalue.name, nt_errstr(status)));
3616                 result = ntstatus_to_werror(status);
3617         }
3618
3619 done:
3620         if (winreg_handle != NULL) {
3621                 WERROR ignore;
3622
3623                 if (is_valid_policy_hnd(&key_hnd)) {
3624                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3625                 }
3626                 if (is_valid_policy_hnd(&hive_hnd)) {
3627                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3628                 }
3629         }
3630
3631         TALLOC_FREE(tmp_ctx);
3632         return result;
3633 }
3634
3635 WERROR winreg_printer_getform1(TALLOC_CTX *mem_ctx,
3636                                const struct auth_serversupplied_info *server_info,
3637                                struct messaging_context *msg_ctx,
3638                                const char *form_name,
3639                                struct spoolss_FormInfo1 *r)
3640 {
3641         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3642         struct dcerpc_binding_handle *winreg_handle = NULL;
3643         struct policy_handle hive_hnd, key_hnd;
3644         struct winreg_String wvalue;
3645         enum winreg_Type type_in;
3646         uint8_t *data_in;
3647         uint32_t data_in_size = 0;
3648         uint32_t value_len = 0;
3649         uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
3650         uint32_t i;
3651         WERROR result;
3652         NTSTATUS status;
3653         TALLOC_CTX *tmp_ctx;
3654
3655         /* check builtin forms first */
3656         for (i = 0; i < num_builtin; i++) {
3657                 if (strequal(builtin_forms1[i].form_name, form_name)) {
3658                         *r = builtin_forms1[i];
3659                         return WERR_OK;
3660                 }
3661         }
3662
3663         tmp_ctx = talloc_stackframe();
3664         if (tmp_ctx == NULL) {
3665                 return WERR_NOMEM;
3666         }
3667
3668         ZERO_STRUCT(hive_hnd);
3669         ZERO_STRUCT(key_hnd);
3670
3671         result = winreg_printer_openkey(tmp_ctx,
3672                                         server_info,
3673                                         msg_ctx,
3674                                         &winreg_handle,
3675                                         TOP_LEVEL_CONTROL_FORMS_KEY,
3676                                         "",
3677                                         true,
3678                                         access_mask,
3679                                         &hive_hnd,
3680                                         &key_hnd);
3681         if (!W_ERROR_IS_OK(result)) {
3682                 DEBUG(2, ("winreg_printer_getform1: Could not open key %s: %s\n",
3683                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3684                 goto done;
3685         }
3686
3687         wvalue.name = form_name;
3688
3689         /*
3690          * call QueryValue once with data == NULL to get the
3691          * needed memory size to be allocated, then allocate
3692          * data buffer and call again.
3693          */
3694         status = dcerpc_winreg_QueryValue(winreg_handle,
3695                                           tmp_ctx,
3696                                           &key_hnd,
3697                                           &wvalue,
3698                                           &type_in,
3699                                           NULL,
3700                                           &data_in_size,
3701                                           &value_len,
3702                                           &result);
3703         if (!NT_STATUS_IS_OK(status)) {
3704                 DEBUG(0, ("winreg_printer_getform1: Could not query value %s: %s\n",
3705                           wvalue.name, nt_errstr(status)));
3706                 result = ntstatus_to_werror(status);
3707                 goto done;
3708         }
3709         if (!W_ERROR_IS_OK(result)) {
3710                 goto done;
3711         }
3712
3713         data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
3714         if (data_in == NULL) {
3715                 result = WERR_NOMEM;
3716                 goto done;
3717         }
3718         value_len = 0;
3719
3720         status = dcerpc_winreg_QueryValue(winreg_handle,
3721                                           tmp_ctx,
3722                                           &key_hnd,
3723                                           &wvalue,
3724                                           &type_in,
3725                                           data_in,
3726                                           &data_in_size,
3727                                           &value_len,
3728                                           &result);
3729         if (!NT_STATUS_IS_OK(status)) {
3730                 DEBUG(0, ("winreg_printer_getform1: Could not query value %s: %s\n",
3731                           wvalue.name, nt_errstr(status)));
3732                 result = ntstatus_to_werror(status);
3733                 goto done;
3734         }
3735         if (!W_ERROR_IS_OK(result)) {
3736                 goto done;
3737         }
3738
3739         r->form_name = talloc_strdup(mem_ctx, form_name);
3740         if (r->form_name == NULL) {
3741                 result = WERR_NOMEM;
3742                 goto done;
3743         }
3744
3745         r->size.width  = IVAL(data_in,  0);
3746         r->size.height = IVAL(data_in,  4);
3747         r->area.left   = IVAL(data_in,  8);
3748         r->area.top    = IVAL(data_in, 12);
3749         r->area.right  = IVAL(data_in, 16);
3750         r->area.bottom = IVAL(data_in, 20);
3751         /* skip index    IVAL(data_in, 24)));*/
3752         r->flags       = (enum spoolss_FormFlags) IVAL(data_in, 28);
3753
3754         result = WERR_OK;
3755 done:
3756         if (winreg_handle != NULL) {
3757                 WERROR ignore;
3758
3759                 if (is_valid_policy_hnd(&key_hnd)) {
3760                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3761                 }
3762                 if (is_valid_policy_hnd(&hive_hnd)) {
3763                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3764                 }
3765         }
3766
3767         TALLOC_FREE(tmp_ctx);
3768         return result;
3769 }
3770
3771 WERROR winreg_add_driver(TALLOC_CTX *mem_ctx,
3772                          const struct auth_serversupplied_info *server_info,
3773                          struct messaging_context *msg_ctx,
3774                          struct spoolss_AddDriverInfoCtr *r,
3775                          const char **driver_name,
3776                          uint32_t *driver_version)
3777 {
3778         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3779         struct dcerpc_binding_handle *winreg_handle = NULL;
3780         struct policy_handle hive_hnd, key_hnd;
3781         struct spoolss_DriverInfo8 info8;
3782         TALLOC_CTX *tmp_ctx = NULL;
3783         WERROR result;
3784
3785         ZERO_STRUCT(hive_hnd);
3786         ZERO_STRUCT(key_hnd);
3787         ZERO_STRUCT(info8);
3788
3789         if (!driver_info_ctr_to_info8(r, &info8)) {
3790                 result = WERR_INVALID_PARAMETER;
3791                 goto done;
3792         }
3793
3794         tmp_ctx = talloc_stackframe();
3795         if (tmp_ctx == NULL) {
3796                 return WERR_NOMEM;
3797         }
3798
3799         result = winreg_printer_opendriver(tmp_ctx,
3800                                            server_info,
3801                                            msg_ctx,
3802                                            info8.driver_name,
3803                                            info8.architecture,
3804                                            info8.version,
3805                                            access_mask, true,
3806                                            &winreg_handle,
3807                                            &hive_hnd,
3808                                            &key_hnd);
3809         if (!W_ERROR_IS_OK(result)) {
3810                 DEBUG(0, ("winreg_add_driver: "
3811                           "Could not open driver key (%s,%s,%d): %s\n",
3812                           info8.driver_name, info8.architecture,
3813                           info8.version, win_errstr(result)));
3814                 goto done;
3815         }
3816
3817         /* TODO: "Attributes" ? */
3818
3819         result = winreg_printer_write_dword(tmp_ctx, winreg_handle,
3820                                             &key_hnd, "Version",
3821                                             info8.version);
3822         if (!W_ERROR_IS_OK(result)) {
3823                 goto done;
3824         }
3825
3826         result = winreg_printer_write_sz(tmp_ctx, winreg_handle,
3827                                          &key_hnd, "Driver",
3828                                          info8.driver_path);
3829         if (!W_ERROR_IS_OK(result)) {
3830                 goto done;
3831         }
3832
3833         result = winreg_printer_write_sz(tmp_ctx, winreg_handle,
3834                                          &key_hnd, "Data File",
3835                                          info8.data_file);
3836         if (!W_ERROR_IS_OK(result)) {
3837                 goto done;
3838         }
3839
3840         result = winreg_printer_write_sz(tmp_ctx, winreg_handle,
3841                                          &key_hnd, "Configuration File",
3842                                          info8.config_file);
3843         if (!W_ERROR_IS_OK(result)) {
3844                 goto done;
3845         }
3846
3847         result = winreg_printer_write_sz(tmp_ctx, winreg_handle,
3848                                          &key_hnd, "Help File",
3849                                          info8.help_file);
3850         if (!W_ERROR_IS_OK(result)) {
3851                 goto done;
3852         }
3853
3854         result = winreg_printer_write_multi_sz(tmp_ctx, winreg_handle,
3855                                                &key_hnd, "Dependent Files",
3856                                                info8.dependent_files);
3857         if (!W_ERROR_IS_OK(result)) {
3858                 goto done;
3859         }
3860
3861         result = winreg_printer_write_sz(tmp_ctx, winreg_handle,
3862                                          &key_hnd, "Monitor",
3863                                          info8.monitor_name);
3864         if (!W_ERROR_IS_OK(result)) {
3865                 goto done;
3866         }
3867
3868         result = winreg_printer_write_sz(tmp_ctx, winreg_handle,
3869                                          &key_hnd, "Datatype",
3870                                          info8.default_datatype);
3871         if (!W_ERROR_IS_OK(result)) {
3872                 goto done;
3873         }
3874
3875         result = winreg_printer_write_multi_sz(tmp_ctx, winreg_handle,
3876                                                &key_hnd, "Previous Names",
3877                                                info8.previous_names);
3878         if (!W_ERROR_IS_OK(result)) {
3879                 goto done;
3880         }
3881
3882         result = winreg_printer_write_date(tmp_ctx, winreg_handle,
3883                                            &key_hnd, "DriverDate",
3884                                            info8.driver_date);
3885         if (!W_ERROR_IS_OK(result)) {
3886                 goto done;
3887         }
3888
3889         result = winreg_printer_write_ver(tmp_ctx, winreg_handle,
3890                                           &key_hnd, "DriverVersion",
3891                                           info8.driver_version);
3892         if (!W_ERROR_IS_OK(result)) {
3893                 goto done;
3894         }
3895
3896         result = winreg_printer_write_sz(tmp_ctx, winreg_handle,
3897                                          &key_hnd, "Manufacturer",
3898                                          info8.manufacturer_name);
3899         if (!W_ERROR_IS_OK(result)) {
3900                 goto done;
3901         }
3902
3903         result = winreg_printer_write_sz(tmp_ctx, winreg_handle,
3904                                          &key_hnd, "OEM URL",
3905                                          info8.manufacturer_url);
3906         if (!W_ERROR_IS_OK(result)) {
3907                 goto done;
3908         }
3909
3910         result = winreg_printer_write_sz(tmp_ctx, winreg_handle,
3911                                          &key_hnd, "HardwareID",
3912                                          info8.hardware_id);
3913         if (!W_ERROR_IS_OK(result)) {
3914                 goto done;
3915         }
3916
3917         result = winreg_printer_write_sz(tmp_ctx, winreg_handle,
3918                                          &key_hnd, "Provider",
3919                                          info8.provider);
3920         if (!W_ERROR_IS_OK(result)) {
3921                 goto done;
3922         }
3923
3924         result = winreg_printer_write_sz(tmp_ctx, winreg_handle,
3925                                          &key_hnd, "Print Processor",
3926                                          info8.print_processor);
3927         if (!W_ERROR_IS_OK(result)) {
3928                 goto done;
3929         }
3930
3931         result = winreg_printer_write_sz(tmp_ctx, winreg_handle,
3932                                          &key_hnd, "VendorSetup",
3933                                          info8.vendor_setup);
3934         if (!W_ERROR_IS_OK(result)) {
3935                 goto done;
3936         }
3937
3938         result = winreg_printer_write_multi_sz(tmp_ctx, winreg_handle,
3939                                                &key_hnd, "Color Profiles",
3940                                                info8.color_profiles);
3941         if (!W_ERROR_IS_OK(result)) {
3942                 goto done;
3943         }
3944
3945         result = winreg_printer_write_sz(tmp_ctx, winreg_handle,
3946                                          &key_hnd, "InfPath",
3947                                          info8.inf_path);
3948         if (!W_ERROR_IS_OK(result)) {
3949                 goto done;
3950         }
3951
3952         result = winreg_printer_write_dword(tmp_ctx, winreg_handle, &key_hnd,
3953                                             "PrinterDriverAttributes",
3954                                             info8.printer_driver_attributes);
3955         if (!W_ERROR_IS_OK(result)) {
3956                 goto done;
3957         }
3958
3959         result = winreg_printer_write_multi_sz(tmp_ctx, winreg_handle,
3960                                                &key_hnd, "CoreDependencies",
3961                                                info8.core_driver_dependencies);
3962         if (!W_ERROR_IS_OK(result)) {
3963                 goto done;
3964         }
3965
3966         result = winreg_printer_write_date(tmp_ctx, winreg_handle,
3967                                            &key_hnd, "MinInboxDriverVerDate",
3968                                            info8.min_inbox_driver_ver_date);
3969         if (!W_ERROR_IS_OK(result)) {
3970                 goto done;
3971         }
3972
3973         result = winreg_printer_write_ver(tmp_ctx, winreg_handle, &key_hnd,
3974                                           "MinInboxDriverVerVersion",
3975                                           info8.min_inbox_driver_ver_version);
3976         if (!W_ERROR_IS_OK(result)) {
3977                 goto done;
3978         }
3979
3980         *driver_name = info8.driver_name;
3981         *driver_version = info8.version;
3982         result = WERR_OK;
3983 done:
3984         if (winreg_handle != NULL) {
3985                 WERROR ignore;
3986
3987                 if (is_valid_policy_hnd(&key_hnd)) {
3988                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3989                 }
3990                 if (is_valid_policy_hnd(&hive_hnd)) {
3991                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3992                 }
3993         }
3994
3995         TALLOC_FREE(tmp_ctx);
3996         return result;
3997 }
3998
3999 WERROR winreg_get_driver(TALLOC_CTX *mem_ctx,
4000                          const struct auth_serversupplied_info *server_info,
4001                          struct messaging_context *msg_ctx,
4002                          const char *architecture,
4003                          const char *driver_name,
4004                          uint32_t driver_version,
4005                          struct spoolss_DriverInfo8 **_info8)
4006 {
4007         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4008         struct dcerpc_binding_handle *winreg_handle = NULL;
4009         struct policy_handle hive_hnd, key_hnd;
4010         struct spoolss_DriverInfo8 i8, *info8;
4011         struct spoolss_PrinterEnumValues *enum_values = NULL;
4012         struct spoolss_PrinterEnumValues *v;
4013         uint32_t num_values = 0;
4014         TALLOC_CTX *tmp_ctx;
4015         WERROR result;
4016         uint32_t i;
4017
4018         ZERO_STRUCT(hive_hnd);
4019         ZERO_STRUCT(key_hnd);
4020         ZERO_STRUCT(i8);
4021
4022         tmp_ctx = talloc_stackframe();
4023         if (tmp_ctx == NULL) {
4024                 return WERR_NOMEM;
4025         }
4026
4027         if (driver_version == DRIVER_ANY_VERSION) {
4028                 /* look for Win2k first and then for NT4 */
4029                 result = winreg_printer_opendriver(tmp_ctx,
4030                                                    server_info,
4031                                                    msg_ctx,
4032                                                    driver_name,
4033                                                    architecture,
4034                                                    3,
4035                                                    access_mask, false,
4036                                                    &winreg_handle,
4037                                                    &hive_hnd,
4038                                                    &key_hnd);
4039                 if (!W_ERROR_IS_OK(result)) {
4040                         result = winreg_printer_opendriver(tmp_ctx,
4041                                                            server_info,
4042                                                            msg_ctx,
4043                                                            driver_name,
4044                                                            architecture,
4045                                                            2,
4046                                                            access_mask, false,
4047                                                            &winreg_handle,
4048                                                            &hive_hnd,
4049                                                            &key_hnd);
4050                 }
4051         } else {
4052                 /* ok normal case */
4053                 result = winreg_printer_opendriver(tmp_ctx,
4054                                                    server_info,
4055                                                    msg_ctx,
4056                                                    driver_name,
4057                                                    architecture,
4058                                                    driver_version,
4059                                                    access_mask, false,
4060                                                    &winreg_handle,
4061                                                    &hive_hnd,
4062                                                    &key_hnd);
4063         }
4064         if (!W_ERROR_IS_OK(result)) {
4065                 DEBUG(5, ("winreg_get_driver: "
4066                           "Could not open driver key (%s,%s,%d): %s\n",
4067                           driver_name, architecture,
4068                           driver_version, win_errstr(result)));
4069                 goto done;
4070         }
4071
4072         result = winreg_printer_enumvalues(tmp_ctx,
4073                                            winreg_handle,
4074                                            &key_hnd,
4075                                            &num_values,
4076                                            &enum_values);
4077         if (!W_ERROR_IS_OK(result)) {
4078                 DEBUG(0, ("winreg_get_driver: "
4079                           "Could not enumerate values for (%s,%s,%d): %s\n",
4080                           driver_name, architecture,
4081                           driver_version, win_errstr(result)));
4082                 goto done;
4083         }
4084
4085         info8 = talloc_zero(tmp_ctx, struct spoolss_DriverInfo8);
4086         if (info8 == NULL) {
4087                 result = WERR_NOMEM;
4088                 goto done;
4089         }
4090
4091         info8->driver_name = talloc_strdup(info8, driver_name);
4092         if (info8->driver_name == NULL) {
4093                 result = WERR_NOMEM;
4094                 goto done;
4095         }
4096
4097         info8->architecture = talloc_strdup(info8, architecture);
4098         if (info8->architecture == NULL) {
4099                 result = WERR_NOMEM;
4100                 goto done;
4101         }
4102
4103         result = WERR_OK;
4104
4105         for (i = 0; i < num_values; i++) {
4106                 const char *tmp_str;
4107                 uint32_t tmp = 0;
4108
4109                 v = &enum_values[i];
4110
4111                 result = winreg_enumval_to_dword(info8, v,
4112                                                  "Version",
4113                                                  &tmp);
4114                 if (NT_STATUS_IS_OK(result)) {
4115                         info8->version = (enum spoolss_DriverOSVersion) tmp;
4116                 }
4117                 CHECK_ERROR(result);
4118
4119                 result = winreg_enumval_to_sz(info8, v,
4120                                               "Driver",
4121                                               &info8->driver_path);
4122                 CHECK_ERROR(result);
4123
4124                 result = winreg_enumval_to_sz(info8, v,
4125                                               "Data File",
4126                                               &info8->data_file);
4127                 CHECK_ERROR(result);
4128
4129                 result = winreg_enumval_to_sz(info8, v,
4130                                               "Configuration File",
4131                                               &info8->config_file);
4132                 CHECK_ERROR(result);
4133
4134                 result = winreg_enumval_to_sz(info8, v,
4135                                               "Help File",
4136                                               &info8->help_file);
4137                 CHECK_ERROR(result);
4138
4139                 result = winreg_enumval_to_multi_sz(info8, v,
4140                                                     "Dependent Files",
4141                                                     &info8->dependent_files);
4142                 CHECK_ERROR(result);
4143
4144                 result = winreg_enumval_to_sz(info8, v,
4145                                               "Monitor",
4146                                               &info8->monitor_name);
4147                 CHECK_ERROR(result);
4148
4149                 result = winreg_enumval_to_sz(info8, v,
4150                                               "Datatype",
4151                                               &info8->default_datatype);
4152                 CHECK_ERROR(result);
4153
4154                 result = winreg_enumval_to_multi_sz(info8, v,
4155                                                     "Previous Names",
4156                                                     &info8->previous_names);
4157                 CHECK_ERROR(result);
4158
4159                 result = winreg_enumval_to_sz(info8, v,
4160                                               "DriverDate",
4161                                               &tmp_str);
4162                 if (W_ERROR_IS_OK(result)) {
4163                         result = winreg_printer_date_to_NTTIME(tmp_str,
4164                                                 &info8->driver_date);
4165                 }
4166                 CHECK_ERROR(result);
4167
4168                 result = winreg_enumval_to_sz(info8, v,
4169                                               "DriverVersion",
4170                                               &tmp_str);
4171                 if (W_ERROR_IS_OK(result)) {
4172                         result = winreg_printer_ver_to_dword(tmp_str,
4173                                                 &info8->driver_version);
4174                 }
4175                 CHECK_ERROR(result);
4176
4177                 result = winreg_enumval_to_sz(info8, v,
4178                                               "Manufacturer",
4179                                               &info8->manufacturer_name);
4180                 CHECK_ERROR(result);
4181
4182                 result = winreg_enumval_to_sz(info8, v,
4183                                               "OEM URL",
4184                                               &info8->manufacturer_url);
4185                 CHECK_ERROR(result);
4186
4187                 result = winreg_enumval_to_sz(info8, v,
4188                                               "HardwareID",
4189                                               &info8->hardware_id);
4190                 CHECK_ERROR(result);
4191
4192                 result = winreg_enumval_to_sz(info8, v,
4193                                               "Provider",
4194                                               &info8->provider);
4195                 CHECK_ERROR(result);
4196
4197                 result = winreg_enumval_to_sz(info8, v,
4198                                               "Print Processor",
4199                                               &info8->print_processor);
4200                 CHECK_ERROR(result);
4201
4202                 result = winreg_enumval_to_sz(info8, v,
4203                                               "VendorSetup",
4204                                               &info8->vendor_setup);
4205                 CHECK_ERROR(result);
4206
4207                 result = winreg_enumval_to_multi_sz(info8, v,
4208                                                     "Color Profiles",
4209                                                     &info8->color_profiles);
4210                 CHECK_ERROR(result);
4211
4212                 result = winreg_enumval_to_sz(info8, v,
4213                                               "InfPath",
4214                                               &info8->inf_path);
4215                 CHECK_ERROR(result);
4216
4217                 result = winreg_enumval_to_dword(info8, v,
4218                                                  "PrinterDriverAttributes",
4219                                                  &info8->printer_driver_attributes);
4220                 CHECK_ERROR(result);
4221
4222                 result = winreg_enumval_to_multi_sz(info8, v,
4223                                                     "CoreDependencies",
4224                                                     &info8->core_driver_dependencies);
4225                 CHECK_ERROR(result);
4226
4227                 result = winreg_enumval_to_sz(info8, v,
4228                                               "MinInboxDriverVerDate",
4229                                               &tmp_str);
4230                 if (W_ERROR_IS_OK(result)) {
4231                         result = winreg_printer_date_to_NTTIME(tmp_str,
4232                                         &info8->min_inbox_driver_ver_date);
4233                 }
4234                 CHECK_ERROR(result);
4235
4236                 result = winreg_enumval_to_sz(info8, v,
4237                                               "MinInboxDriverVerVersion",
4238                                               &tmp_str);
4239                 if (W_ERROR_IS_OK(result)) {
4240                         result = winreg_printer_ver_to_dword(tmp_str,
4241                                         &info8->min_inbox_driver_ver_version);
4242                 }
4243                 CHECK_ERROR(result);
4244         }
4245
4246         if (!W_ERROR_IS_OK(result)) {
4247                 DEBUG(0, ("winreg_enumval_to_TYPE() failed "
4248                           "for %s: %s\n", v->value_name,
4249                           win_errstr(result)));
4250                 goto done;
4251         }
4252
4253         *_info8 = talloc_steal(mem_ctx, info8);
4254         result = WERR_OK;
4255 done:
4256         if (winreg_handle != NULL) {
4257                 WERROR ignore;
4258
4259                 if (is_valid_policy_hnd(&key_hnd)) {
4260                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
4261                 }
4262                 if (is_valid_policy_hnd(&hive_hnd)) {
4263                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
4264                 }
4265         }
4266
4267         TALLOC_FREE(tmp_ctx);
4268         return result;
4269 }
4270
4271 WERROR winreg_del_driver(TALLOC_CTX *mem_ctx,
4272                          const struct auth_serversupplied_info *server_info,
4273                          struct messaging_context *msg_ctx,
4274                          struct spoolss_DriverInfo8 *info8,
4275                          uint32_t version)
4276 {
4277         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4278         struct dcerpc_binding_handle *winreg_handle = NULL;
4279         struct policy_handle hive_hnd, key_hnd;
4280         TALLOC_CTX *tmp_ctx;
4281         char *key_name;
4282         WERROR result;
4283
4284         ZERO_STRUCT(hive_hnd);
4285         ZERO_STRUCT(key_hnd);
4286
4287         tmp_ctx = talloc_stackframe();
4288         if (tmp_ctx == NULL) {
4289                 return WERR_NOMEM;
4290         }
4291
4292         /* test that the key exists */
4293         result = winreg_printer_opendriver(tmp_ctx,
4294                                            server_info,
4295                                            msg_ctx,
4296                                            info8->driver_name,
4297                                            info8->architecture,
4298                                            version,
4299                                            access_mask, false,
4300                                            &winreg_handle,
4301                                            &hive_hnd,
4302                                            &key_hnd);
4303         if (!W_ERROR_IS_OK(result)) {
4304                 /* key doesn't exist */
4305                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
4306                         result = WERR_OK;
4307                         goto done;
4308                 }
4309
4310                 DEBUG(5, ("winreg_del_driver: "
4311                           "Could not open driver (%s,%s,%u): %s\n",
4312                           info8->driver_name, info8->architecture,
4313                           version, win_errstr(result)));
4314                 goto done;
4315         }
4316
4317
4318         if (is_valid_policy_hnd(&key_hnd)) {
4319                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &result);
4320         }
4321
4322         key_name = talloc_asprintf(tmp_ctx,
4323                                    "%s\\Environments\\%s\\Drivers\\Version-%u",
4324                                    TOP_LEVEL_CONTROL_KEY,
4325                                    info8->architecture, version);
4326         if (key_name == NULL) {
4327                 result = WERR_NOMEM;
4328                 goto done;
4329         }
4330
4331         result = winreg_printer_delete_subkeys(tmp_ctx,
4332                                                winreg_handle,
4333                                                &hive_hnd,
4334                                                access_mask,
4335                                                key_name);
4336         if (!W_ERROR_IS_OK(result)) {
4337                 DEBUG(0, ("winreg_del_driver: "
4338                           "Could not open driver (%s,%s,%u): %s\n",
4339                           info8->driver_name, info8->architecture,
4340                           version, win_errstr(result)));
4341                 goto done;
4342         }
4343
4344         result = WERR_OK;
4345 done:
4346         if (winreg_handle != NULL) {
4347                 WERROR ignore;
4348
4349                 if (is_valid_policy_hnd(&key_hnd)) {
4350                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
4351                 }
4352                 if (is_valid_policy_hnd(&hive_hnd)) {
4353                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
4354                 }
4355         }
4356
4357         TALLOC_FREE(tmp_ctx);
4358         return result;
4359 }
4360
4361 WERROR winreg_get_driver_list(TALLOC_CTX *mem_ctx,
4362                               const struct auth_serversupplied_info *server_info,
4363                               struct messaging_context *msg_ctx,
4364                               const char *architecture,
4365                               uint32_t version,
4366                               uint32_t *num_drivers,
4367                               const char ***drivers_p)
4368 {
4369         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4370         struct dcerpc_binding_handle *winreg_handle = NULL;
4371         struct policy_handle hive_hnd, key_hnd;
4372         const char **drivers;
4373         TALLOC_CTX *tmp_ctx;
4374         WERROR result;
4375
4376         *num_drivers = 0;
4377         *drivers_p = NULL;
4378
4379         ZERO_STRUCT(hive_hnd);
4380         ZERO_STRUCT(key_hnd);
4381
4382         tmp_ctx = talloc_stackframe();
4383         if (tmp_ctx == NULL) {
4384                 return WERR_NOMEM;
4385         }
4386
4387         /* use NULL for the driver name so we open the key that is
4388          * parent of all drivers for this architecture and version */
4389         result = winreg_printer_opendriver(tmp_ctx,
4390                                            server_info,
4391                                            msg_ctx,
4392                                            NULL,
4393                                            architecture,
4394                                            version,
4395                                            access_mask, false,
4396                                            &winreg_handle,
4397                                            &hive_hnd,
4398                                            &key_hnd);
4399         if (!W_ERROR_IS_OK(result)) {
4400                 DEBUG(5, ("winreg_get_driver_list: "
4401                           "Could not open key (%s,%u): %s\n",
4402                           architecture, version, win_errstr(result)));
4403                 result = WERR_OK;
4404                 goto done;
4405         }
4406
4407         result = winreg_printer_enumkeys(tmp_ctx,
4408                                          winreg_handle,
4409                                          &key_hnd,
4410                                          num_drivers,
4411                                          &drivers);
4412         if (!W_ERROR_IS_OK(result)) {
4413                 DEBUG(0, ("winreg_get_driver_list: "
4414                           "Could not enumerate drivers for (%s,%u): %s\n",
4415                           architecture, version, win_errstr(result)));
4416                 goto done;
4417         }
4418
4419         *drivers_p = talloc_steal(mem_ctx, drivers);
4420
4421         result = WERR_OK;
4422 done:
4423         if (winreg_handle != NULL) {
4424                 WERROR ignore;
4425
4426                 if (is_valid_policy_hnd(&key_hnd)) {
4427                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
4428                 }
4429                 if (is_valid_policy_hnd(&hive_hnd)) {
4430                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
4431                 }
4432         }
4433
4434         TALLOC_FREE(tmp_ctx);
4435         return result;
4436 }
4437