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