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