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