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