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