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