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