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