s3: Fix Coverity ID 242715 Uninitialized scalar variable
[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         WERROR ignore;
940         NTSTATUS status;
941         TALLOC_CTX *tmp_ctx;
942
943         tmp_ctx = talloc_stackframe();
944         if (tmp_ctx == NULL) {
945                 return WERR_NOMEM;
946         }
947
948         path = winreg_printer_data_keyname(tmp_ctx, sharename);
949         if (path == NULL) {
950                 TALLOC_FREE(tmp_ctx);
951                 return WERR_NOMEM;
952         }
953
954         ZERO_STRUCT(hive_hnd);
955         ZERO_STRUCT(key_hnd);
956
957         result = winreg_printer_openkey(tmp_ctx,
958                                         winreg_handle,
959                                         path,
960                                         "",
961                                         true,
962                                         access_mask,
963                                         &hive_hnd,
964                                         &key_hnd);
965         if (!W_ERROR_IS_OK(result)) {
966                 DEBUG(0, ("winreg_update_printer: Could not open key %s: %s\n",
967                         path, win_errstr(result)));
968                 goto done;
969         }
970
971         if (info2_mask & SPOOLSS_PRINTER_INFO_ATTRIBUTES) {
972                 status = dcerpc_winreg_set_dword(tmp_ctx,
973                                                  winreg_handle,
974                                                  &key_hnd,
975                                                  "Attributes",
976                                                  info2->attributes,
977                                                  &result);
978                 if (!NT_STATUS_IS_OK(status)) {
979                         result = ntstatus_to_werror(status);
980                 }
981                 if (!W_ERROR_IS_OK(result)) {
982                         goto done;
983                 }
984         }
985
986 #if 0
987         if (info2_mask & SPOOLSS_PRINTER_INFO_AVERAGEPPM) {
988                 status = dcerpc_winreg_set_dword(tmp_ctx,
989                                                  winreg_handle,
990                                                  &key_hnd,
991                                                  "AveragePpm",
992                                                  info2->attributes,
993                                                  &result);
994                 if (!NT_STATUS_IS_OK(status)) {
995                         result = ntstatus_to_werror(status);
996                 }
997                 if (!W_ERROR_IS_OK(result)) {
998                         goto done;
999                 }
1000         }
1001 #endif
1002
1003         if (info2_mask & SPOOLSS_PRINTER_INFO_COMMENT) {
1004                 status = dcerpc_winreg_set_sz(tmp_ctx,
1005                                               winreg_handle,
1006                                               &key_hnd,
1007                                               "Description",
1008                                               info2->comment,
1009                                               &result);
1010                 if (!NT_STATUS_IS_OK(status)) {
1011                         result = ntstatus_to_werror(status);
1012                 }
1013                 if (!W_ERROR_IS_OK(result)) {
1014                         goto done;
1015                 }
1016         }
1017
1018         if (info2_mask & SPOOLSS_PRINTER_INFO_DATATYPE) {
1019                 status = dcerpc_winreg_set_sz(tmp_ctx,
1020                                               winreg_handle,
1021                                               &key_hnd,
1022                                               "Datatype",
1023                                               info2->datatype,
1024                                               &result);
1025                 if (!NT_STATUS_IS_OK(status)) {
1026                         result = ntstatus_to_werror(status);
1027                 }
1028                 if (!W_ERROR_IS_OK(result)) {
1029                         goto done;
1030                 }
1031         }
1032
1033         if (info2_mask & SPOOLSS_PRINTER_INFO_DEFAULTPRIORITY) {
1034                 status = dcerpc_winreg_set_dword(tmp_ctx,
1035                                                  winreg_handle,
1036                                                  &key_hnd,
1037                                                  "Default Priority",
1038                                                  info2->defaultpriority,
1039                                                  &result);
1040                 if (!NT_STATUS_IS_OK(status)) {
1041                         result = ntstatus_to_werror(status);
1042                 }
1043                 if (!W_ERROR_IS_OK(result)) {
1044                         goto done;
1045                 }
1046         }
1047
1048         if (info2_mask & SPOOLSS_PRINTER_INFO_DEVMODE) {
1049                 /*
1050                  * Some client drivers freak out if there is a NULL devmode
1051                  * (probably the driver is not checking before accessing
1052                  * the devmode pointer)   --jerry
1053                  */
1054                 if (devmode == NULL && lp_default_devmode(snum) && info2 != NULL) {
1055                         result = spoolss_create_default_devmode(tmp_ctx,
1056                                                                 info2->printername,
1057                                                                 &devmode);
1058                         if (!W_ERROR_IS_OK(result)) {
1059                                 goto done;
1060                         }
1061                 }
1062
1063                 if (devmode->size != (ndr_size_spoolss_DeviceMode(devmode, 0) - devmode->__driverextra_length)) {
1064                         result = WERR_INVALID_PARAM;
1065                         goto done;
1066                 }
1067
1068                 ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, devmode,
1069                                 (ndr_push_flags_fn_t) ndr_push_spoolss_DeviceMode);
1070                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1071                         DEBUG(0, ("winreg_update_printer: Failed to marshall device mode\n"));
1072                         result = WERR_NOMEM;
1073                         goto done;
1074                 }
1075
1076                 status = dcerpc_winreg_set_binary(tmp_ctx,
1077                                                   winreg_handle,
1078                                                   &key_hnd,
1079                                                   "Default DevMode",
1080                                                   &blob,
1081                                                   &result);
1082                 if (!NT_STATUS_IS_OK(status)) {
1083                         result = ntstatus_to_werror(status);
1084                 }
1085                 if (!W_ERROR_IS_OK(result)) {
1086                         goto done;
1087                 }
1088         }
1089
1090         if (info2_mask & SPOOLSS_PRINTER_INFO_DRIVERNAME) {
1091                 status = dcerpc_winreg_set_sz(tmp_ctx,
1092                                               winreg_handle,
1093                                               &key_hnd,
1094                                               "Printer Driver",
1095                                               info2->drivername,
1096                                               &result);
1097                 if (!NT_STATUS_IS_OK(status)) {
1098                         result = ntstatus_to_werror(status);
1099                 }
1100                 if (!W_ERROR_IS_OK(result)) {
1101                         goto done;
1102                 }
1103         }
1104
1105         if (info2_mask & SPOOLSS_PRINTER_INFO_LOCATION) {
1106                 status = dcerpc_winreg_set_sz(tmp_ctx,
1107                                               winreg_handle,
1108                                               &key_hnd,
1109                                               "Location",
1110                                               info2->location,
1111                                               &result);
1112                 if (!NT_STATUS_IS_OK(status)) {
1113                         result = ntstatus_to_werror(status);
1114                 }
1115                 if (!W_ERROR_IS_OK(result)) {
1116                         goto done;
1117                 }
1118         }
1119
1120         if (info2_mask & SPOOLSS_PRINTER_INFO_PARAMETERS) {
1121                 status = dcerpc_winreg_set_sz(tmp_ctx,
1122                                               winreg_handle,
1123                                               &key_hnd,
1124                                               "Parameters",
1125                                               info2->parameters,
1126                                               &result);
1127                 if (!NT_STATUS_IS_OK(status)) {
1128                         result = ntstatus_to_werror(status);
1129                 }
1130                 if (!W_ERROR_IS_OK(result)) {
1131                         goto done;
1132                 }
1133         }
1134
1135         if (info2_mask & SPOOLSS_PRINTER_INFO_PORTNAME) {
1136                 status = dcerpc_winreg_set_sz(tmp_ctx,
1137                                               winreg_handle,
1138                                               &key_hnd,
1139                                               "Port",
1140                                               info2->portname,
1141                                               &result);
1142                 if (!NT_STATUS_IS_OK(status)) {
1143                         result = ntstatus_to_werror(status);
1144                 }
1145                 if (!W_ERROR_IS_OK(result)) {
1146                         goto done;
1147                 }
1148         }
1149
1150         if (info2_mask & SPOOLSS_PRINTER_INFO_PRINTERNAME) {
1151                 /*
1152                  * in addprinter: no servername and the printer is the name
1153                  * in setprinter: servername is \\server
1154                  *                and printer is \\server\\printer
1155                  *
1156                  * Samba manages only local printers.
1157                  * we currently don't support things like i
1158                  * path=\\other_server\printer
1159                  *
1160                  * We only store the printername, not \\server\printername
1161                  */
1162                 const char *p = strrchr(info2->printername, '\\');
1163                 if (p == NULL) {
1164                         p = info2->printername;
1165                 } else {
1166                         p++;
1167                 }
1168                 status = dcerpc_winreg_set_sz(tmp_ctx,
1169                                               winreg_handle,
1170                                               &key_hnd,
1171                                               "Name",
1172                                               p,
1173                                               &result);
1174                 if (!NT_STATUS_IS_OK(status)) {
1175                         result = ntstatus_to_werror(status);
1176                 }
1177                 if (!W_ERROR_IS_OK(result)) {
1178                         goto done;
1179                 }
1180         }
1181
1182         if (info2_mask & SPOOLSS_PRINTER_INFO_PRINTPROCESSOR) {
1183                 status = dcerpc_winreg_set_sz(tmp_ctx,
1184                                               winreg_handle,
1185                                               &key_hnd,
1186                                               "Print Processor",
1187                                               info2->printprocessor,
1188                                               &result);
1189                 if (!NT_STATUS_IS_OK(status)) {
1190                         result = ntstatus_to_werror(status);
1191                 }
1192                 if (!W_ERROR_IS_OK(result)) {
1193                         goto done;
1194                 }
1195         }
1196
1197         if (info2_mask & SPOOLSS_PRINTER_INFO_PRIORITY) {
1198                 status = dcerpc_winreg_set_dword(tmp_ctx,
1199                                                  winreg_handle,
1200                                                  &key_hnd,
1201                                                  "Priority",
1202                                                  info2->priority,
1203                                                  &result);
1204                 if (!NT_STATUS_IS_OK(status)) {
1205                         result = ntstatus_to_werror(status);
1206                 }
1207                 if (!W_ERROR_IS_OK(result)) {
1208                         goto done;
1209                 }
1210         }
1211
1212         if (info2_mask & SPOOLSS_PRINTER_INFO_SECDESC) {
1213                 /*
1214                  * We need a security descriptor, if it isn't specified by
1215                  * AddPrinter{Ex} then create a default descriptor.
1216                  */
1217                 if (secdesc == NULL) {
1218                         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
1219                         if (!W_ERROR_IS_OK(result)) {
1220                                 goto done;
1221                         }
1222                 }
1223                 result = winreg_set_printer_secdesc(tmp_ctx,
1224                                                     winreg_handle,
1225                                                     sharename,
1226                                                     secdesc);
1227                 if (!W_ERROR_IS_OK(result)) {
1228                         goto done;
1229                 }
1230         }
1231
1232         if (info2_mask & SPOOLSS_PRINTER_INFO_SEPFILE) {
1233                 status = dcerpc_winreg_set_sz(tmp_ctx,
1234                                               winreg_handle,
1235                                               &key_hnd,
1236                                               "Separator File",
1237                                               info2->sepfile,
1238                                               &result);
1239                 if (!NT_STATUS_IS_OK(status)) {
1240                         result = ntstatus_to_werror(status);
1241                 }
1242                 if (!W_ERROR_IS_OK(result)) {
1243                         goto done;
1244                 }
1245         }
1246
1247         if (info2_mask & SPOOLSS_PRINTER_INFO_SHARENAME) {
1248                 status = dcerpc_winreg_set_sz(tmp_ctx,
1249                                               winreg_handle,
1250                                               &key_hnd,
1251                                               "Share Name",
1252                                               info2->sharename,
1253                                               &result);
1254                 if (!NT_STATUS_IS_OK(status)) {
1255                         result = ntstatus_to_werror(status);
1256                 }
1257                 if (!W_ERROR_IS_OK(result)) {
1258                         goto done;
1259                 }
1260         }
1261
1262         if (info2_mask & SPOOLSS_PRINTER_INFO_STARTTIME) {
1263                 status = dcerpc_winreg_set_dword(tmp_ctx,
1264                                                  winreg_handle,
1265                                                  &key_hnd,
1266                                                  "StartTime",
1267                                                  info2->starttime,
1268                                                  &result);
1269                 if (!NT_STATUS_IS_OK(status)) {
1270                         result = ntstatus_to_werror(status);
1271                 }
1272                 if (!W_ERROR_IS_OK(result)) {
1273                         goto done;
1274                 }
1275         }
1276
1277         if (info2_mask & SPOOLSS_PRINTER_INFO_STATUS) {
1278                 status = dcerpc_winreg_set_dword(tmp_ctx,
1279                                                  winreg_handle,
1280                                                  &key_hnd,
1281                                                  "Status",
1282                                                  info2->status,
1283                                                  &result);
1284                 if (!NT_STATUS_IS_OK(status)) {
1285                         result = ntstatus_to_werror(status);
1286                 }
1287                 if (!W_ERROR_IS_OK(result)) {
1288                         goto done;
1289                 }
1290         }
1291
1292         if (info2_mask & SPOOLSS_PRINTER_INFO_UNTILTIME) {
1293                 status = dcerpc_winreg_set_dword(tmp_ctx,
1294                                                  winreg_handle,
1295                                                  &key_hnd,
1296                                                  "UntilTime",
1297                                                  info2->untiltime,
1298                                                  &result);
1299                 if (!NT_STATUS_IS_OK(status)) {
1300                         result = ntstatus_to_werror(status);
1301                 }
1302                 if (!W_ERROR_IS_OK(result)) {
1303                         goto done;
1304                 }
1305         }
1306
1307         status = dcerpc_winreg_set_dword(tmp_ctx,
1308                                          winreg_handle,
1309                                          &key_hnd,
1310                                          "ChangeID",
1311                                          winreg_printer_rev_changeid(),
1312                                          &result);
1313         if (!NT_STATUS_IS_OK(status)) {
1314                 result = ntstatus_to_werror(status);
1315         }
1316         if (!W_ERROR_IS_OK(result)) {
1317                 goto done;
1318         }
1319
1320         result = WERR_OK;
1321 done:
1322         if (is_valid_policy_hnd(&key_hnd)) {
1323                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1324         }
1325         if (is_valid_policy_hnd(&hive_hnd)) {
1326                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1327         }
1328
1329         TALLOC_FREE(tmp_ctx);
1330         return result;
1331 }
1332
1333 WERROR winreg_get_printer(TALLOC_CTX *mem_ctx,
1334                           struct dcerpc_binding_handle *winreg_handle,
1335                           const char *printer,
1336                           struct spoolss_PrinterInfo2 **pinfo2)
1337 {
1338         struct spoolss_PrinterInfo2 *info2;
1339         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1340         struct policy_handle hive_hnd, key_hnd;
1341         struct spoolss_PrinterEnumValues enum_value;
1342         struct spoolss_PrinterEnumValues *v = NULL;
1343         enum ndr_err_code ndr_err;
1344         DATA_BLOB blob;
1345         int snum = lp_servicenumber(printer);
1346         uint32_t num_values = 0;
1347         uint32_t i;
1348         char *path;
1349         NTSTATUS status;
1350         WERROR result = WERR_OK;
1351         WERROR ignore;
1352         const char **enum_names = NULL;
1353         enum winreg_Type *enum_types = NULL;
1354         DATA_BLOB *enum_data_blobs = NULL;
1355         TALLOC_CTX *tmp_ctx;
1356
1357         tmp_ctx = talloc_stackframe();
1358         if (tmp_ctx == NULL) {
1359                 return WERR_NOMEM;
1360         }
1361
1362         path = winreg_printer_data_keyname(tmp_ctx, printer);
1363         if (path == NULL) {
1364                 TALLOC_FREE(tmp_ctx);
1365                 return WERR_NOMEM;
1366         }
1367
1368         result = winreg_printer_openkey(tmp_ctx,
1369                                         winreg_handle,
1370                                         path,
1371                                         "",
1372                                         false,
1373                                         access_mask,
1374                                         &hive_hnd,
1375                                         &key_hnd);
1376         if (!W_ERROR_IS_OK(result)) {
1377                 DEBUG(2, ("winreg_get_printer: Could not open key %s: %s\n",
1378                           path, win_errstr(result)));
1379                 goto done;
1380         }
1381
1382         status = dcerpc_winreg_enumvals(tmp_ctx,
1383                                         winreg_handle,
1384                                         &key_hnd,
1385                                         &num_values,
1386                                         &enum_names,
1387                                         &enum_types,
1388                                         &enum_data_blobs,
1389                                         &result);
1390         if (!NT_STATUS_IS_OK(status)){
1391                 result = ntstatus_to_werror(status);
1392         }
1393
1394         if (!W_ERROR_IS_OK(result)) {
1395                 DEBUG(0, ("winreg_get_printer: Could not enumerate values in %s: %s\n",
1396                           path, win_errstr(result)));
1397                 goto done;
1398         }
1399
1400         info2 = talloc_zero(tmp_ctx, struct spoolss_PrinterInfo2);
1401         if (info2 == NULL) {
1402                 result = WERR_NOMEM;
1403                 goto done;
1404         }
1405
1406         FILL_STRING(info2, EMPTY_STRING, info2->servername);
1407         FILL_STRING(info2, EMPTY_STRING, info2->printername);
1408         FILL_STRING(info2, EMPTY_STRING, info2->sharename);
1409         FILL_STRING(info2, EMPTY_STRING, info2->portname);
1410         FILL_STRING(info2, EMPTY_STRING, info2->drivername);
1411         FILL_STRING(info2, EMPTY_STRING, info2->comment);
1412         FILL_STRING(info2, EMPTY_STRING, info2->location);
1413         FILL_STRING(info2, EMPTY_STRING, info2->sepfile);
1414         FILL_STRING(info2, EMPTY_STRING, info2->printprocessor);
1415         FILL_STRING(info2, EMPTY_STRING, info2->datatype);
1416         FILL_STRING(info2, EMPTY_STRING, info2->parameters);
1417
1418         for (i = 0; i < num_values; i++) {
1419                 enum_value.value_name = enum_names[i];
1420                 enum_value.value_name_len = 2*strlen_m_term(enum_names[i]);
1421                 enum_value.type = enum_types[i];
1422                 enum_value.data_length = enum_data_blobs[i].length;
1423                 enum_value.data = NULL;
1424                 if (enum_value.data_length != 0){
1425                         enum_value.data = &enum_data_blobs[i];
1426                 }
1427                 v = &enum_value;
1428
1429                 result = winreg_enumval_to_sz(info2,
1430                                               v,
1431                                               "Name",
1432                                               &info2->printername);
1433                 CHECK_ERROR(result);
1434
1435                 result = winreg_enumval_to_sz(info2,
1436                                               v,
1437                                               "Share Name",
1438                                               &info2->sharename);
1439                 CHECK_ERROR(result);
1440
1441                 result = winreg_enumval_to_sz(info2,
1442                                               v,
1443                                               "Port",
1444                                               &info2->portname);
1445                 CHECK_ERROR(result);
1446
1447                 result = winreg_enumval_to_sz(info2,
1448                                               v,
1449                                               "Description",
1450                                               &info2->comment);
1451                 CHECK_ERROR(result);
1452
1453                 result = winreg_enumval_to_sz(info2,
1454                                               v,
1455                                               "Location",
1456                                               &info2->location);
1457                 CHECK_ERROR(result);
1458
1459                 result = winreg_enumval_to_sz(info2,
1460                                               v,
1461                                               "Separator File",
1462                                               &info2->sepfile);
1463                 CHECK_ERROR(result);
1464
1465                 result = winreg_enumval_to_sz(info2,
1466                                               v,
1467                                               "Print Processor",
1468                                               &info2->printprocessor);
1469                 CHECK_ERROR(result);
1470
1471                 result = winreg_enumval_to_sz(info2,
1472                                               v,
1473                                               "Datatype",
1474                                               &info2->datatype);
1475                 CHECK_ERROR(result);
1476
1477                 result = winreg_enumval_to_sz(info2,
1478                                               v,
1479                                               "Parameters",
1480                                               &info2->parameters);
1481                 CHECK_ERROR(result);
1482
1483                 result = winreg_enumval_to_sz(info2,
1484                                               v,
1485                                               "Printer Driver",
1486                                               &info2->drivername);
1487                 CHECK_ERROR(result);
1488
1489                 result = winreg_enumval_to_dword(info2,
1490                                                  v,
1491                                                  "Attributes",
1492                                                  &info2->attributes);
1493                 CHECK_ERROR(result);
1494
1495                 result = winreg_enumval_to_dword(info2,
1496                                                  v,
1497                                                  "Priority",
1498                                                  &info2->priority);
1499                 CHECK_ERROR(result);
1500
1501                 result = winreg_enumval_to_dword(info2,
1502                                                  v,
1503                                                  "Default Priority",
1504                                                  &info2->defaultpriority);
1505                 CHECK_ERROR(result);
1506
1507                 result = winreg_enumval_to_dword(info2,
1508                                                  v,
1509                                                  "StartTime",
1510                                                  &info2->starttime);
1511                 CHECK_ERROR(result);
1512
1513                 result = winreg_enumval_to_dword(info2,
1514                                                  v,
1515                                                  "UntilTime",
1516                                                  &info2->untiltime);
1517                 CHECK_ERROR(result);
1518
1519                 result = winreg_enumval_to_dword(info2,
1520                                                  v,
1521                                                  "Status",
1522                                                  &info2->status);
1523                 CHECK_ERROR(result);
1524
1525                 result = winreg_enumval_to_dword(info2,
1526                                                  v,
1527                                                  "StartTime",
1528                                                  &info2->starttime);
1529                 CHECK_ERROR(result);
1530         }
1531
1532         if (!W_ERROR_IS_OK(result)) {
1533                 DEBUG(0, ("winreg_get_printer: winreg_enumval_to_TYPE() failed "
1534                                         "for %s: %s\n",
1535                                         v->value_name,
1536                                         win_errstr(result)));
1537                 goto done;
1538         }
1539
1540         /* Construct the Device Mode */
1541         status = dcerpc_winreg_query_binary(tmp_ctx,
1542                                             winreg_handle,
1543                                             &key_hnd,
1544                                             "Default DevMode",
1545                                             &blob,
1546                                             &result);
1547         if (!NT_STATUS_IS_OK(status)) {
1548                 result = ntstatus_to_werror(status);
1549         }
1550         if (W_ERROR_IS_OK(result)) {
1551                 info2->devmode = talloc_zero(info2, struct spoolss_DeviceMode);
1552                 if (info2->devmode == NULL) {
1553                         result = WERR_NOMEM;
1554                         goto done;
1555                 }
1556                 ndr_err = ndr_pull_struct_blob(&blob,
1557                                                info2->devmode,
1558                                                info2->devmode,
1559                                                (ndr_pull_flags_fn_t) ndr_pull_spoolss_DeviceMode);
1560                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1561                         DEBUG(0, ("winreg_get_printer: Failed to unmarshall device mode\n"));
1562                         result = WERR_NOMEM;
1563                         goto done;
1564                 }
1565         }
1566
1567         if (info2->devmode == NULL && lp_default_devmode(snum)) {
1568                 result = spoolss_create_default_devmode(info2,
1569                                                         info2->printername,
1570                                                         &info2->devmode);
1571                 if (!W_ERROR_IS_OK(result)) {
1572                         goto done;
1573                 }
1574         }
1575
1576         if (info2->devmode) {
1577                 info2->devmode->size = ndr_size_spoolss_DeviceMode(info2->devmode, 0) - info2->devmode->driverextra_data.length;
1578         }
1579
1580         result = winreg_get_printer_secdesc(info2,
1581                                             winreg_handle,
1582                                             printer,
1583                                             &info2->secdesc);
1584         if (!W_ERROR_IS_OK(result)) {
1585                 goto done;
1586         }
1587
1588         /* Fix for OS/2 drivers. */
1589         if (get_remote_arch() == RA_OS2) {
1590                 spoolss_map_to_os2_driver(info2, &info2->drivername);
1591         }
1592
1593         if (pinfo2) {
1594                 *pinfo2 = talloc_move(mem_ctx, &info2);
1595         }
1596
1597         result = WERR_OK;
1598 done:
1599         if (is_valid_policy_hnd(&key_hnd)) {
1600                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1601         }
1602         if (is_valid_policy_hnd(&hive_hnd)) {
1603                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1604         }
1605
1606         TALLOC_FREE(tmp_ctx);
1607         return result;
1608 }
1609
1610 WERROR winreg_get_printer_secdesc(TALLOC_CTX *mem_ctx,
1611                                   struct dcerpc_binding_handle *winreg_handle,
1612                                   const char *sharename,
1613                                   struct spoolss_security_descriptor **psecdesc)
1614 {
1615         struct spoolss_security_descriptor *secdesc;
1616         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1617         struct policy_handle hive_hnd, key_hnd;
1618         const char *path;
1619         TALLOC_CTX *tmp_ctx;
1620         NTSTATUS status;
1621         WERROR result;
1622         WERROR ignore;
1623
1624         tmp_ctx = talloc_stackframe();
1625         if (tmp_ctx == NULL) {
1626                 return WERR_NOMEM;
1627         }
1628
1629         path = winreg_printer_data_keyname(tmp_ctx, sharename);
1630         if (path == NULL) {
1631                 talloc_free(tmp_ctx);
1632                 return WERR_NOMEM;
1633         }
1634
1635         ZERO_STRUCT(hive_hnd);
1636         ZERO_STRUCT(key_hnd);
1637
1638         result = winreg_printer_openkey(tmp_ctx,
1639                                         winreg_handle,
1640                                         path,
1641                                         "",
1642                                         false,
1643                                         access_mask,
1644                                         &hive_hnd,
1645                                         &key_hnd);
1646         if (!W_ERROR_IS_OK(result)) {
1647                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1648                         goto create_default;
1649                 }
1650                 goto done;
1651         }
1652
1653         status = dcerpc_winreg_query_sd(tmp_ctx,
1654                                         winreg_handle,
1655                                         &key_hnd,
1656                                         "Security",
1657                                         &secdesc,
1658                                         &result);
1659         if (!NT_STATUS_IS_OK(status)) {
1660                 result = ntstatus_to_werror(status);
1661         }
1662         if (!W_ERROR_IS_OK(result)) {
1663                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1664
1665                         if (is_valid_policy_hnd(&key_hnd)) {
1666                                 dcerpc_winreg_CloseKey(winreg_handle,
1667                                                        tmp_ctx,
1668                                                        &key_hnd,
1669                                                        &ignore);
1670                         }
1671
1672                         if (is_valid_policy_hnd(&hive_hnd)) {
1673                                 dcerpc_winreg_CloseKey(winreg_handle,
1674                                                        tmp_ctx,
1675                                                        &hive_hnd,
1676                                                        &ignore);
1677                         }
1678                         goto create_default;
1679                 }
1680                 goto done;
1681         }
1682
1683         if (psecdesc) {
1684                 *psecdesc = talloc_move(mem_ctx, &secdesc);
1685         }
1686
1687         result = WERR_OK;
1688         goto done;
1689
1690 create_default:
1691         result = winreg_printer_openkey(tmp_ctx,
1692                                         winreg_handle,
1693                                         path,
1694                                         "",
1695                                         true,
1696                                         access_mask,
1697                                         &hive_hnd,
1698                                         &key_hnd);
1699         if (!W_ERROR_IS_OK(result)) {
1700                 goto done;
1701         }
1702
1703         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
1704         if (!W_ERROR_IS_OK(result)) {
1705                 goto done;
1706         }
1707
1708         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
1709            this security descriptor has been created when winbindd was
1710            down.  Take ownership of security descriptor. */
1711         if (dom_sid_equal(secdesc->owner_sid, &global_sid_World)) {
1712                 struct dom_sid owner_sid;
1713
1714                 /* Change sd owner to workgroup administrator */
1715
1716                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
1717                         struct spoolss_security_descriptor *new_secdesc;
1718                         size_t size;
1719
1720                         /* Create new sd */
1721                         sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
1722
1723                         new_secdesc = make_sec_desc(tmp_ctx,
1724                                                     secdesc->revision,
1725                                                     secdesc->type,
1726                                                     &owner_sid,
1727                                                     secdesc->group_sid,
1728                                                     secdesc->sacl,
1729                                                     secdesc->dacl,
1730                                                     &size);
1731
1732                         if (new_secdesc == NULL) {
1733                                 result = WERR_NOMEM;
1734                                 goto done;
1735                         }
1736
1737                         /* Swap with other one */
1738                         secdesc = new_secdesc;
1739                 }
1740         }
1741
1742         status = dcerpc_winreg_set_sd(tmp_ctx,
1743                                           winreg_handle,
1744                                           &key_hnd,
1745                                           "Security",
1746                                           secdesc,
1747                                           &result);
1748         if (!NT_STATUS_IS_OK(status)) {
1749                 result = ntstatus_to_werror(status);
1750         }
1751         if (!W_ERROR_IS_OK(result)) {
1752                 return result;
1753         }
1754
1755         if (psecdesc) {
1756                 *psecdesc = talloc_move(mem_ctx, &secdesc);
1757         }
1758
1759         result = WERR_OK;
1760 done:
1761         if (is_valid_policy_hnd(&key_hnd)) {
1762                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1763         }
1764         if (is_valid_policy_hnd(&hive_hnd)) {
1765                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1766         }
1767
1768         talloc_free(tmp_ctx);
1769         return result;
1770 }
1771
1772 WERROR winreg_set_printer_secdesc(TALLOC_CTX *mem_ctx,
1773                                   struct dcerpc_binding_handle *winreg_handle,
1774                                   const char *sharename,
1775                                   const struct spoolss_security_descriptor *secdesc)
1776 {
1777         const struct spoolss_security_descriptor *new_secdesc = secdesc;
1778         struct spoolss_security_descriptor *old_secdesc;
1779         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1780         struct policy_handle hive_hnd, key_hnd;
1781         const char *path;
1782         TALLOC_CTX *tmp_ctx;
1783         NTSTATUS status;
1784         WERROR result;
1785         WERROR ignore;
1786
1787         tmp_ctx = talloc_stackframe();
1788         if (tmp_ctx == NULL) {
1789                 return WERR_NOMEM;
1790         }
1791
1792         path = winreg_printer_data_keyname(tmp_ctx, sharename);
1793         if (path == NULL) {
1794                 talloc_free(tmp_ctx);
1795                 return WERR_NOMEM;
1796         }
1797
1798         /*
1799          * The old owner and group sids of the security descriptor are not
1800          * present when new ACEs are added or removed by changing printer
1801          * permissions through NT.  If they are NULL in the new security
1802          * descriptor then copy them over from the old one.
1803          */
1804         if (!secdesc->owner_sid || !secdesc->group_sid) {
1805                 struct dom_sid *owner_sid, *group_sid;
1806                 struct security_acl *dacl, *sacl;
1807                 size_t size;
1808
1809                 result = winreg_get_printer_secdesc(tmp_ctx,
1810                                                     winreg_handle,
1811                                                     sharename,
1812                                                     &old_secdesc);
1813                 if (!W_ERROR_IS_OK(result)) {
1814                         talloc_free(tmp_ctx);
1815                         return result;
1816                 }
1817
1818                 /* Pick out correct owner and group sids */
1819                 owner_sid = secdesc->owner_sid ?
1820                             secdesc->owner_sid :
1821                             old_secdesc->owner_sid;
1822
1823                 group_sid = secdesc->group_sid ?
1824                             secdesc->group_sid :
1825                             old_secdesc->group_sid;
1826
1827                 dacl = secdesc->dacl ?
1828                        secdesc->dacl :
1829                        old_secdesc->dacl;
1830
1831                 sacl = secdesc->sacl ?
1832                        secdesc->sacl :
1833                        old_secdesc->sacl;
1834
1835                 /* Make a deep copy of the security descriptor */
1836                 new_secdesc = make_sec_desc(tmp_ctx,
1837                                             secdesc->revision,
1838                                             secdesc->type,
1839                                             owner_sid,
1840                                             group_sid,
1841                                             sacl,
1842                                             dacl,
1843                                             &size);
1844                 if (new_secdesc == NULL) {
1845                         talloc_free(tmp_ctx);
1846                         return WERR_NOMEM;
1847                 }
1848         }
1849
1850         ZERO_STRUCT(hive_hnd);
1851         ZERO_STRUCT(key_hnd);
1852
1853         result = winreg_printer_openkey(tmp_ctx,
1854                                         winreg_handle,
1855                                         path,
1856                                         "",
1857                                         false,
1858                                         access_mask,
1859                                         &hive_hnd,
1860                                         &key_hnd);
1861         if (!W_ERROR_IS_OK(result)) {
1862                 goto done;
1863         }
1864
1865         status = dcerpc_winreg_set_sd(tmp_ctx,
1866                                       winreg_handle,
1867                                       &key_hnd,
1868                                       "Security",
1869                                       new_secdesc,
1870                                       &result);
1871         if (!NT_STATUS_IS_OK(status)) {
1872                 result = ntstatus_to_werror(status);
1873         }
1874
1875 done:
1876         if (is_valid_policy_hnd(&key_hnd)) {
1877                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1878         }
1879         if (is_valid_policy_hnd(&hive_hnd)) {
1880                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1881         }
1882
1883         talloc_free(tmp_ctx);
1884         return result;
1885 }
1886
1887 /* Set printer data over the winreg pipe. */
1888 WERROR winreg_set_printer_dataex(TALLOC_CTX *mem_ctx,
1889                                  struct dcerpc_binding_handle *winreg_handle,
1890                                  const char *printer,
1891                                  const char *key,
1892                                  const char *value,
1893                                  enum winreg_Type type,
1894                                  uint8_t *data,
1895                                  uint32_t data_size)
1896 {
1897         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1898         struct policy_handle hive_hnd, key_hnd;
1899         struct winreg_String wvalue = { 0, };
1900         char *path;
1901         WERROR result = WERR_OK;
1902         WERROR ignore;
1903         NTSTATUS status;
1904         TALLOC_CTX *tmp_ctx;
1905
1906         tmp_ctx = talloc_stackframe();
1907         if (tmp_ctx == NULL) {
1908                 return WERR_NOMEM;
1909         }
1910
1911         path = winreg_printer_data_keyname(tmp_ctx, printer);
1912         if (path == NULL) {
1913                 TALLOC_FREE(tmp_ctx);
1914                 return WERR_NOMEM;
1915         }
1916
1917         ZERO_STRUCT(hive_hnd);
1918         ZERO_STRUCT(key_hnd);
1919
1920         DEBUG(8, ("winreg_set_printer_dataex: Open printer key %s, value %s, access_mask: 0x%05x for [%s]\n",
1921                         key, value, access_mask, printer));
1922         result = winreg_printer_openkey(tmp_ctx,
1923                                         winreg_handle,
1924                                         path,
1925                                         key,
1926                                         true,
1927                                         access_mask,
1928                                         &hive_hnd,
1929                                         &key_hnd);
1930         if (!W_ERROR_IS_OK(result)) {
1931                 DEBUG(0, ("winreg_set_printer_dataex: Could not open key %s: %s\n",
1932                           key, win_errstr(result)));
1933                 goto done;
1934         }
1935
1936         wvalue.name = value;
1937         status = dcerpc_winreg_SetValue(winreg_handle,
1938                                         tmp_ctx,
1939                                         &key_hnd,
1940                                         wvalue,
1941                                         type,
1942                                         data,
1943                                         data_size,
1944                                         &result);
1945         if (!NT_STATUS_IS_OK(status)) {
1946                 DEBUG(0, ("winreg_set_printer_dataex: Could not set value %s: %s\n",
1947                           value, nt_errstr(status)));
1948                 result = ntstatus_to_werror(status);
1949         }
1950
1951 done:
1952         if (is_valid_policy_hnd(&key_hnd)) {
1953                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1954         }
1955         if (is_valid_policy_hnd(&hive_hnd)) {
1956                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1957         }
1958
1959         TALLOC_FREE(tmp_ctx);
1960         return result;
1961 }
1962
1963 /* Get printer data over a winreg pipe. */
1964 WERROR winreg_get_printer_dataex(TALLOC_CTX *mem_ctx,
1965                                  struct dcerpc_binding_handle *winreg_handle,
1966                                  const char *printer,
1967                                  const char *key,
1968                                  const char *value,
1969                                  enum winreg_Type *type,
1970                                  uint8_t **data,
1971                                  uint32_t *data_size)
1972 {
1973         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1974         struct policy_handle hive_hnd, key_hnd;
1975         struct winreg_String wvalue;
1976         enum winreg_Type type_in = REG_NONE;
1977         char *path;
1978         uint8_t *data_in = NULL;
1979         uint32_t data_in_size = 0;
1980         uint32_t value_len = 0;
1981         WERROR result = WERR_OK;
1982         WERROR ignore;
1983         NTSTATUS status;
1984         TALLOC_CTX *tmp_ctx;
1985
1986         tmp_ctx = talloc_stackframe();
1987         if (tmp_ctx == NULL) {
1988                 return WERR_NOMEM;
1989         }
1990
1991         path = winreg_printer_data_keyname(tmp_ctx, printer);
1992         if (path == NULL) {
1993                 TALLOC_FREE(tmp_ctx);
1994                 return WERR_NOMEM;
1995         }
1996
1997         ZERO_STRUCT(hive_hnd);
1998         ZERO_STRUCT(key_hnd);
1999
2000         result = winreg_printer_openkey(tmp_ctx,
2001                                         winreg_handle,
2002                                         path,
2003                                         key,
2004                                         false,
2005                                         access_mask,
2006                                         &hive_hnd,
2007                                         &key_hnd);
2008         if (!W_ERROR_IS_OK(result)) {
2009                 DEBUG(2, ("winreg_get_printer_dataex: Could not open key %s: %s\n",
2010                           key, win_errstr(result)));
2011                 goto done;
2012         }
2013
2014         wvalue.name = value;
2015
2016         /*
2017          * call QueryValue once with data == NULL to get the
2018          * needed memory size to be allocated, then allocate
2019          * data buffer and call again.
2020          */
2021         status = dcerpc_winreg_QueryValue(winreg_handle,
2022                                           tmp_ctx,
2023                                           &key_hnd,
2024                                           &wvalue,
2025                                           &type_in,
2026                                           NULL,
2027                                           &data_in_size,
2028                                           &value_len,
2029                                           &result);
2030         if (!NT_STATUS_IS_OK(status)) {
2031                 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2032                           value, nt_errstr(status)));
2033                 result = ntstatus_to_werror(status);
2034                 goto done;
2035         }
2036         if (!W_ERROR_IS_OK(result)) {
2037                 DEBUG(2, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2038                           value, win_errstr(result)));
2039                 goto done;
2040         }
2041
2042         data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
2043         if (data_in == NULL) {
2044                 result = WERR_NOMEM;
2045                 goto done;
2046         }
2047         value_len = 0;
2048
2049         status = dcerpc_winreg_QueryValue(winreg_handle,
2050                                           tmp_ctx,
2051                                           &key_hnd,
2052                                           &wvalue,
2053                                           &type_in,
2054                                           data_in,
2055                                           &data_in_size,
2056                                           &value_len,
2057                                           &result);
2058         if (!NT_STATUS_IS_OK(status)) {
2059                 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2060                           value, nt_errstr(status)));
2061                 result = ntstatus_to_werror(status);
2062                 goto done;
2063         }
2064         if (!W_ERROR_IS_OK(result)) {
2065                 DEBUG(2, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2066                           value, win_errstr(result)));
2067                 goto done;
2068         }
2069
2070         *type = type_in;
2071         *data_size = data_in_size;
2072         if (data_in_size) {
2073                 *data = talloc_move(mem_ctx, &data_in);
2074         }
2075
2076         result = WERR_OK;
2077 done:
2078         if (is_valid_policy_hnd(&key_hnd)) {
2079                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2080         }
2081         if (is_valid_policy_hnd(&hive_hnd)) {
2082                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2083         }
2084
2085         TALLOC_FREE(tmp_ctx);
2086         return result;
2087 }
2088
2089 /* Enumerate on the values of a given key and provide the data. */
2090 WERROR winreg_enum_printer_dataex(TALLOC_CTX *mem_ctx,
2091                                   struct dcerpc_binding_handle *winreg_handle,
2092                                   const char *printer,
2093                                   const char *key,
2094                                   uint32_t *pnum_values,
2095                                   struct spoolss_PrinterEnumValues **penum_values)
2096 {
2097         uint32_t i;
2098         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2099         struct policy_handle hive_hnd, key_hnd;
2100
2101         struct spoolss_PrinterEnumValues *enum_values = NULL;
2102         uint32_t num_values = 0;
2103         char *path;
2104         WERROR result = WERR_OK;
2105         WERROR ignore;
2106         NTSTATUS status;
2107         const char **enum_names = NULL;
2108         enum winreg_Type *enum_types = NULL;
2109         DATA_BLOB *enum_data_blobs = NULL;
2110
2111         TALLOC_CTX *tmp_ctx;
2112
2113         tmp_ctx = talloc_stackframe();
2114         if (tmp_ctx == NULL) {
2115                 return WERR_NOMEM;
2116         }
2117
2118         path = winreg_printer_data_keyname(tmp_ctx, printer);
2119         if (path == NULL) {
2120                 TALLOC_FREE(tmp_ctx);
2121                 return WERR_NOMEM;
2122         }
2123
2124         result = winreg_printer_openkey(tmp_ctx,
2125                                         winreg_handle,
2126                                         path,
2127                                         key,
2128                                         false,
2129                                         access_mask,
2130                                         &hive_hnd,
2131                                         &key_hnd);
2132         if (!W_ERROR_IS_OK(result)) {
2133                 DEBUG(2, ("winreg_enum_printer_dataex: Could not open key %s: %s\n",
2134                           key, win_errstr(result)));
2135                 goto done;
2136         }
2137
2138         status = dcerpc_winreg_enumvals(tmp_ctx,
2139                                         winreg_handle,
2140                                         &key_hnd,
2141                                         &num_values,
2142                                         &enum_names,
2143                                         &enum_types,
2144                                         &enum_data_blobs,
2145                                         &result);
2146         if (!NT_STATUS_IS_OK(status)){
2147                 result = ntstatus_to_werror(status);
2148         }
2149
2150         if (!W_ERROR_IS_OK(result)) {
2151                 DEBUG(0, ("winreg_enum_printer_dataex: Could not enumerate values in %s: %s\n",
2152                           key, win_errstr(result)));
2153                 goto done;
2154         }
2155
2156         enum_values = talloc_array(tmp_ctx, struct spoolss_PrinterEnumValues, num_values);
2157         if (enum_values == NULL){
2158                 result = WERR_NOMEM;
2159                 DEBUG(0, ("winreg_enum_printer_dataex: Could not enumerate values in %s: %s\n",
2160                           key, win_errstr(result)));
2161                 goto done;
2162         }
2163
2164         for (i = 0; i < num_values; i++){
2165                 enum_values[i].value_name = enum_names[i];
2166                 enum_values[i].value_name_len = strlen_m_term(enum_names[i]) * 2;
2167                 enum_values[i].type = enum_types[i];
2168                 enum_values[i].data_length = enum_data_blobs[i].length;
2169                 enum_values[i].data = NULL;
2170
2171                 if (enum_values[i].data_length != 0){
2172                         enum_values[i].data = &enum_data_blobs[i];
2173                 }
2174         }
2175
2176         talloc_steal(enum_values, enum_names);
2177         talloc_steal(enum_values, enum_data_blobs);
2178
2179         *pnum_values = num_values;
2180         if (penum_values) {
2181                 *penum_values = talloc_move(mem_ctx, &enum_values);
2182         }
2183
2184         result = WERR_OK;
2185 done:
2186         if (is_valid_policy_hnd(&key_hnd)) {
2187                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2188         }
2189         if (is_valid_policy_hnd(&hive_hnd)) {
2190                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2191         }
2192
2193         TALLOC_FREE(tmp_ctx);
2194         return result;
2195 }
2196
2197 /* Delete printer data over a winreg pipe. */
2198 WERROR winreg_delete_printer_dataex(TALLOC_CTX *mem_ctx,
2199                                     struct dcerpc_binding_handle *winreg_handle,
2200                                     const char *printer,
2201                                     const char *key,
2202                                     const char *value)
2203 {
2204         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2205         struct policy_handle hive_hnd, key_hnd;
2206         struct winreg_String wvalue = { 0, };
2207         char *path;
2208         WERROR result = WERR_OK;
2209         WERROR ignore;
2210         NTSTATUS status;
2211
2212         TALLOC_CTX *tmp_ctx;
2213
2214         tmp_ctx = talloc_stackframe();
2215         if (tmp_ctx == NULL) {
2216                 return WERR_NOMEM;
2217         }
2218
2219         path = winreg_printer_data_keyname(tmp_ctx, printer);
2220         if (path == NULL) {
2221                 TALLOC_FREE(tmp_ctx);
2222                 return WERR_NOMEM;
2223         }
2224
2225         ZERO_STRUCT(hive_hnd);
2226         ZERO_STRUCT(key_hnd);
2227
2228         result = winreg_printer_openkey(tmp_ctx,
2229                                         winreg_handle,
2230                                         path,
2231                                         key,
2232                                         false,
2233                                         access_mask,
2234                                         &hive_hnd,
2235                                         &key_hnd);
2236         if (!W_ERROR_IS_OK(result)) {
2237                 DEBUG(0, ("winreg_delete_printer_dataex: Could not open key %s: %s\n",
2238                           key, win_errstr(result)));
2239                 goto done;
2240         }
2241
2242         wvalue.name = value;
2243         status = dcerpc_winreg_DeleteValue(winreg_handle,
2244                                            tmp_ctx,
2245                                            &key_hnd,
2246                                            wvalue,
2247                                            &result);
2248         if (!NT_STATUS_IS_OK(status)) {
2249                 DEBUG(0, ("winreg_delete_printer_dataex: Could not delete value %s: %s\n",
2250                           value, nt_errstr(status)));
2251                 result = ntstatus_to_werror(status);
2252         }
2253
2254 done:
2255         if (is_valid_policy_hnd(&key_hnd)) {
2256                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2257         }
2258         if (is_valid_policy_hnd(&hive_hnd)) {
2259                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2260         }
2261
2262         TALLOC_FREE(tmp_ctx);
2263         return result;
2264 }
2265
2266 /* Enumerate on the subkeys of a given key and provide the data. */
2267 WERROR winreg_enum_printer_key(TALLOC_CTX *mem_ctx,
2268                                struct dcerpc_binding_handle *winreg_handle,
2269                                const char *printer,
2270                                const char *key,
2271                                uint32_t *pnum_subkeys,
2272                                const char ***psubkeys)
2273 {
2274         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2275         struct policy_handle hive_hnd, key_hnd;
2276         char *path;
2277         const char **subkeys = NULL;
2278         uint32_t num_subkeys = -1;
2279
2280         WERROR result = WERR_OK;
2281         WERROR ignore;
2282         NTSTATUS status;
2283
2284         TALLOC_CTX *tmp_ctx;
2285
2286         tmp_ctx = talloc_stackframe();
2287         if (tmp_ctx == NULL) {
2288                 return WERR_NOMEM;
2289         }
2290
2291         path = winreg_printer_data_keyname(tmp_ctx, printer);
2292         if (path == NULL) {
2293                 TALLOC_FREE(tmp_ctx);
2294                 return WERR_NOMEM;
2295         }
2296
2297         ZERO_STRUCT(hive_hnd);
2298         ZERO_STRUCT(key_hnd);
2299
2300         result = winreg_printer_openkey(tmp_ctx,
2301                                         winreg_handle,
2302                                         path,
2303                                         key,
2304                                         false,
2305                                         access_mask,
2306                                         &hive_hnd,
2307                                         &key_hnd);
2308         if (!W_ERROR_IS_OK(result)) {
2309                 DEBUG(2, ("winreg_enum_printer_key: Could not open key %s: %s\n",
2310                           key, win_errstr(result)));
2311                 goto done;
2312         }
2313
2314         status = dcerpc_winreg_enum_keys(tmp_ctx,
2315                                          winreg_handle,
2316                                          &key_hnd,
2317                                          &num_subkeys,
2318                                          &subkeys,
2319                                          &result);
2320         if (!NT_STATUS_IS_OK(status)) {
2321                 result = ntstatus_to_werror(status);
2322         }
2323         if (!W_ERROR_IS_OK(result)) {
2324                 DEBUG(0, ("winreg_enum_printer_key: Could not enumerate subkeys in %s: %s\n",
2325                           key, win_errstr(result)));
2326                 goto done;
2327         }
2328
2329         *pnum_subkeys = num_subkeys;
2330         if (psubkeys) {
2331                 *psubkeys = talloc_move(mem_ctx, &subkeys);
2332         }
2333
2334         result = WERR_OK;
2335 done:
2336         if (is_valid_policy_hnd(&key_hnd)) {
2337                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2338         }
2339         if (is_valid_policy_hnd(&hive_hnd)) {
2340                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2341         }
2342
2343         TALLOC_FREE(tmp_ctx);
2344         return result;
2345 }
2346
2347 /* Delete a key with subkeys of a given printer. */
2348 WERROR winreg_delete_printer_key(TALLOC_CTX *mem_ctx,
2349                                  struct dcerpc_binding_handle *winreg_handle,
2350                                  const char *printer,
2351                                  const char *key)
2352 {
2353         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2354         struct policy_handle hive_hnd, key_hnd;
2355         char *keyname;
2356         char *path;
2357         WERROR result;
2358         WERROR ignore;
2359         NTSTATUS status;
2360         TALLOC_CTX *tmp_ctx;
2361
2362         tmp_ctx = talloc_stackframe();
2363         if (tmp_ctx == NULL) {
2364                 return WERR_NOMEM;
2365         }
2366
2367         path = winreg_printer_data_keyname(tmp_ctx, printer);
2368         if (path == NULL) {
2369                 TALLOC_FREE(tmp_ctx);
2370                 return WERR_NOMEM;
2371         }
2372
2373         result = winreg_printer_openkey(tmp_ctx,
2374                                         winreg_handle,
2375                                         path,
2376                                         key,
2377                                         false,
2378                                         access_mask,
2379                                         &hive_hnd,
2380                                         &key_hnd);
2381         if (!W_ERROR_IS_OK(result)) {
2382                 /* key doesn't exist */
2383                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2384                         result = WERR_OK;
2385                         goto done;
2386                 }
2387
2388                 DEBUG(0, ("winreg_delete_printer_key: Could not open key %s: %s\n",
2389                           key, win_errstr(result)));
2390                 goto done;
2391         }
2392
2393         if (is_valid_policy_hnd(&key_hnd)) {
2394                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &result);
2395         }
2396
2397         if (key == NULL || key[0] == '\0') {
2398                 keyname = path;
2399         } else {
2400                 keyname = talloc_asprintf(tmp_ctx,
2401                                           "%s\\%s",
2402                                           path,
2403                                           key);
2404                 if (keyname == NULL) {
2405                         result = WERR_NOMEM;
2406                         goto done;
2407                 }
2408         }
2409
2410         status = dcerpc_winreg_delete_subkeys_recursive(tmp_ctx,
2411                                                         winreg_handle,
2412                                                         &hive_hnd,
2413                                                         access_mask,
2414                                                         keyname,
2415                                                         &result);
2416
2417         if (!NT_STATUS_IS_OK(status)) {
2418                 DEBUG(0, ("winreg_delete_printer_key: Could not delete key %s: %s\n",
2419                           key, nt_errstr(status)));
2420                 result = ntstatus_to_werror(status);
2421                 goto done;
2422         }
2423
2424         if (!W_ERROR_IS_OK(result)) {
2425                 DEBUG(0, ("winreg_delete_printer_key: Could not delete key %s: %s\n",
2426                           key, win_errstr(result)));
2427                 goto done;
2428         }
2429
2430 done:
2431         if (is_valid_policy_hnd(&key_hnd)) {
2432                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2433         }
2434         if (is_valid_policy_hnd(&hive_hnd)) {
2435                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2436         }
2437
2438         TALLOC_FREE(tmp_ctx);
2439         return result;
2440 }
2441
2442 WERROR winreg_printer_update_changeid(TALLOC_CTX *mem_ctx,
2443                                       struct dcerpc_binding_handle *winreg_handle,
2444                                       const char *printer)
2445 {
2446         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2447         struct policy_handle hive_hnd, key_hnd;
2448         char *path;
2449         NTSTATUS status;
2450         WERROR result;
2451         WERROR ignore;
2452         TALLOC_CTX *tmp_ctx;
2453
2454         tmp_ctx = talloc_stackframe();
2455         if (tmp_ctx == NULL) {
2456                 return WERR_NOMEM;
2457         }
2458
2459         path = winreg_printer_data_keyname(tmp_ctx, printer);
2460         if (path == NULL) {
2461                 TALLOC_FREE(tmp_ctx);
2462                 return WERR_NOMEM;
2463         }
2464
2465         ZERO_STRUCT(hive_hnd);
2466         ZERO_STRUCT(key_hnd);
2467
2468         result = winreg_printer_openkey(tmp_ctx,
2469                                         winreg_handle,
2470                                         path,
2471                                         "",
2472                                         false,
2473                                         access_mask,
2474                                         &hive_hnd,
2475                                         &key_hnd);
2476         if (!W_ERROR_IS_OK(result)) {
2477                 DEBUG(0, ("winreg_printer_update_changeid: Could not open key %s: %s\n",
2478                           path, win_errstr(result)));
2479                 goto done;
2480         }
2481
2482         status = dcerpc_winreg_set_dword(tmp_ctx,
2483                                          winreg_handle,
2484                                          &key_hnd,
2485                                          "ChangeID",
2486                                          winreg_printer_rev_changeid(),
2487                                          &result);
2488         if (!NT_STATUS_IS_OK(status)) {
2489                 result = ntstatus_to_werror(status);
2490         }
2491         if (!W_ERROR_IS_OK(result)) {
2492                 goto done;
2493         }
2494
2495         result = WERR_OK;
2496 done:
2497         if (is_valid_policy_hnd(&key_hnd)) {
2498                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2499         }
2500         if (is_valid_policy_hnd(&hive_hnd)) {
2501                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2502         }
2503
2504         TALLOC_FREE(tmp_ctx);
2505         return result;
2506 }
2507
2508 WERROR winreg_printer_get_changeid(TALLOC_CTX *mem_ctx,
2509                                    struct dcerpc_binding_handle *winreg_handle,
2510                                    const char *printer,
2511                                    uint32_t *pchangeid)
2512 {
2513         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2514         struct policy_handle hive_hnd, key_hnd;
2515         uint32_t changeid = 0;
2516         char *path;
2517         NTSTATUS status;
2518         WERROR result;
2519         WERROR ignore;
2520         TALLOC_CTX *tmp_ctx;
2521
2522         tmp_ctx = talloc_stackframe();
2523         if (tmp_ctx == NULL) {
2524                 return WERR_NOMEM;
2525         }
2526
2527         path = winreg_printer_data_keyname(tmp_ctx, printer);
2528         if (path == NULL) {
2529                 TALLOC_FREE(tmp_ctx);
2530                 return WERR_NOMEM;
2531         }
2532
2533         ZERO_STRUCT(hive_hnd);
2534         ZERO_STRUCT(key_hnd);
2535
2536         result = winreg_printer_openkey(tmp_ctx,
2537                                         winreg_handle,
2538                                         path,
2539                                         "",
2540                                         false,
2541                                         access_mask,
2542                                         &hive_hnd,
2543                                         &key_hnd);
2544         if (!W_ERROR_IS_OK(result)) {
2545                 DEBUG(2, ("winreg_printer_get_changeid: Could not open key %s: %s\n",
2546                           path, win_errstr(result)));
2547                 goto done;
2548         }
2549
2550         DEBUG(10, ("winreg_printer_get_changeid: get changeid from %s\n", path));
2551
2552         status = dcerpc_winreg_query_dword(tmp_ctx,
2553                                            winreg_handle,
2554                                            &key_hnd,
2555                                            "ChangeID",
2556                                            &changeid,
2557                                            &result);
2558         if (!NT_STATUS_IS_OK(status)) {
2559                 result = ntstatus_to_werror(status);
2560         }
2561         if (!W_ERROR_IS_OK(result)) {
2562                 goto done;
2563         }
2564
2565         if (pchangeid) {
2566                 *pchangeid = changeid;
2567         }
2568
2569         result = WERR_OK;
2570 done:
2571         if (is_valid_policy_hnd(&key_hnd)) {
2572                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2573         }
2574         if (is_valid_policy_hnd(&hive_hnd)) {
2575                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2576         }
2577
2578         TALLOC_FREE(tmp_ctx);
2579         return result;
2580 }
2581
2582 /*
2583  * The special behaviour of the spoolss forms is documented at the website:
2584  *
2585  * Managing Win32 Printserver Forms
2586  * http://unixwiz.net/techtips/winspooler-forms.html
2587  */
2588
2589 WERROR winreg_printer_addform1(TALLOC_CTX *mem_ctx,
2590                                struct dcerpc_binding_handle *winreg_handle,
2591                                struct spoolss_AddFormInfo1 *form)
2592 {
2593         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2594         struct policy_handle hive_hnd, key_hnd;
2595         struct winreg_String wvalue = { 0, };
2596         DATA_BLOB blob;
2597         uint32_t num_info = 0;
2598         union spoolss_FormInfo *info = NULL;
2599         uint32_t i;
2600         WERROR result;
2601         WERROR ignore;
2602         NTSTATUS status;
2603         TALLOC_CTX *tmp_ctx;
2604
2605         tmp_ctx = talloc_stackframe();
2606         if (tmp_ctx == NULL) {
2607                 return WERR_NOMEM;
2608         }
2609
2610         ZERO_STRUCT(hive_hnd);
2611         ZERO_STRUCT(key_hnd);
2612
2613         result = winreg_printer_openkey(tmp_ctx,
2614                                         winreg_handle,
2615                                         TOP_LEVEL_CONTROL_FORMS_KEY,
2616                                         "",
2617                                         true,
2618                                         access_mask,
2619                                         &hive_hnd,
2620                                         &key_hnd);
2621         if (!W_ERROR_IS_OK(result)) {
2622                 DEBUG(0, ("winreg_printer_addform1: Could not open key %s: %s\n",
2623                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2624                 goto done;
2625         }
2626
2627         result = winreg_printer_enumforms1(tmp_ctx, winreg_handle,
2628                                            &num_info, &info);
2629         if (!W_ERROR_IS_OK(result)) {
2630                 DEBUG(0, ("winreg_printer_addform: Could not enum keys %s: %s\n",
2631                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2632                 goto done;
2633         }
2634
2635         /* If form name already exists or is builtin return ALREADY_EXISTS */
2636         for (i = 0; i < num_info; i++) {
2637                 if (strequal(info[i].info1.form_name, form->form_name)) {
2638                         result = WERR_FILE_EXISTS;
2639                         goto done;
2640                 }
2641         }
2642
2643         wvalue.name = form->form_name;
2644
2645         blob = data_blob_talloc(tmp_ctx, NULL, 32);
2646         SIVAL(blob.data,  0, form->size.width);
2647         SIVAL(blob.data,  4, form->size.height);
2648         SIVAL(blob.data,  8, form->area.left);
2649         SIVAL(blob.data, 12, form->area.top);
2650         SIVAL(blob.data, 16, form->area.right);
2651         SIVAL(blob.data, 20, form->area.bottom);
2652         SIVAL(blob.data, 24, num_info + 1); /* FIXME */
2653         SIVAL(blob.data, 28, form->flags);
2654
2655         status = dcerpc_winreg_SetValue(winreg_handle,
2656                                         tmp_ctx,
2657                                         &key_hnd,
2658                                         wvalue,
2659                                         REG_BINARY,
2660                                         blob.data,
2661                                         blob.length,
2662                                         &result);
2663         if (!NT_STATUS_IS_OK(status)) {
2664                 DEBUG(0, ("winreg_printer_addform1: Could not set value %s: %s\n",
2665                           wvalue.name, nt_errstr(status)));
2666                 result = ntstatus_to_werror(status);
2667         }
2668
2669 done:
2670         if (is_valid_policy_hnd(&key_hnd)) {
2671                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2672         }
2673         if (is_valid_policy_hnd(&hive_hnd)) {
2674                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2675         }
2676
2677         TALLOC_FREE(info);
2678         TALLOC_FREE(tmp_ctx);
2679         return result;
2680 }
2681
2682 WERROR winreg_printer_enumforms1(TALLOC_CTX *mem_ctx,
2683                                  struct dcerpc_binding_handle *winreg_handle,
2684                                  uint32_t *pnum_info,
2685                                  union spoolss_FormInfo **pinfo)
2686 {
2687         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2688         struct policy_handle hive_hnd, key_hnd;
2689         union spoolss_FormInfo *info;
2690         struct spoolss_PrinterEnumValues *enum_values = NULL;
2691         uint32_t num_values = 0;
2692         uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
2693         uint32_t i;
2694         WERROR result;
2695         WERROR ignore;
2696         NTSTATUS status;
2697         const char **enum_names = NULL;
2698         enum winreg_Type *enum_types = NULL;
2699         DATA_BLOB *enum_data_blobs = NULL;
2700         TALLOC_CTX *tmp_ctx;
2701
2702         tmp_ctx = talloc_stackframe();
2703         if (tmp_ctx == NULL) {
2704                 return WERR_NOMEM;
2705         }
2706
2707         ZERO_STRUCT(hive_hnd);
2708         ZERO_STRUCT(key_hnd);
2709
2710         result = winreg_printer_openkey(tmp_ctx,
2711                                         winreg_handle,
2712                                         TOP_LEVEL_CONTROL_FORMS_KEY,
2713                                         "",
2714                                         true,
2715                                         access_mask,
2716                                         &hive_hnd,
2717                                         &key_hnd);
2718         if (!W_ERROR_IS_OK(result)) {
2719                 /* key doesn't exist */
2720                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2721                         result = WERR_OK;
2722                         goto done;
2723                 }
2724
2725                 DEBUG(0, ("winreg_printer_enumforms1: Could not open key %s: %s\n",
2726                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2727                 goto done;
2728         }
2729
2730         status = dcerpc_winreg_enumvals(tmp_ctx,
2731                                         winreg_handle,
2732                                         &key_hnd,
2733                                         &num_values,
2734                                         &enum_names,
2735                                         &enum_types,
2736                                         &enum_data_blobs,
2737                                         &result);
2738         if (!NT_STATUS_IS_OK(status)){
2739                 result = ntstatus_to_werror(status);
2740         }
2741
2742         if (!W_ERROR_IS_OK(result)) {
2743                 DEBUG(0, ("winreg_printer_enumforms1: Could not enumerate values in %s: %s\n",
2744                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2745                 goto done;
2746         }
2747
2748         enum_values = talloc_zero_array(tmp_ctx,
2749                                         struct spoolss_PrinterEnumValues,
2750                                         num_values);
2751         if (enum_values == NULL){
2752                 result = WERR_NOMEM;
2753                 goto done;
2754         }
2755
2756         for (i = 0; i < num_values; i++){
2757                 enum_values[i].value_name = enum_names[i];
2758                 enum_values[i].value_name_len = strlen_m_term(enum_names[i]) * 2;
2759                 enum_values[i].type = enum_types[i];
2760                 enum_values[i].data_length = enum_data_blobs[i].length;
2761                 enum_values[i].data = NULL;
2762                 if (enum_values[i].data_length != 0){
2763                         enum_values[i].data = &enum_data_blobs[i];
2764                 }
2765         }
2766
2767         if (!W_ERROR_IS_OK(result)) {
2768                 DEBUG(0, ("winreg_printer_enumforms1: Could not enumerate values in %s: %s\n",
2769                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2770                 goto done;
2771         }
2772
2773         info = talloc_array(tmp_ctx, union spoolss_FormInfo, num_builtin + num_values);
2774         if (info == NULL) {
2775                 result = WERR_NOMEM;
2776                 goto done;
2777         }
2778
2779         /* Enumerate BUILTIN forms */
2780         for (i = 0; i < num_builtin; i++) {
2781                 info[i].info1 = builtin_forms1[i];
2782         }
2783
2784         /* Enumerate registry forms */
2785         for (i = 0; i < num_values; i++) {
2786                 union spoolss_FormInfo val;
2787
2788                 if (enum_values[i].type != REG_BINARY ||
2789                     enum_values[i].data_length != 32) {
2790                         continue;
2791                 }
2792
2793                 val.info1.form_name = talloc_strdup(info, enum_values[i].value_name);
2794                 if (val.info1.form_name == NULL) {
2795                         result = WERR_NOMEM;
2796                         goto done;
2797                 }
2798
2799                 val.info1.size.width  = IVAL(enum_values[i].data->data,  0);
2800                 val.info1.size.height = IVAL(enum_values[i].data->data,  4);
2801                 val.info1.area.left   = IVAL(enum_values[i].data->data,  8);
2802                 val.info1.area.top    = IVAL(enum_values[i].data->data, 12);
2803                 val.info1.area.right  = IVAL(enum_values[i].data->data, 16);
2804                 val.info1.area.bottom = IVAL(enum_values[i].data->data, 20);
2805                 /* skip form index      IVAL(enum_values[i].data->data, 24)));*/
2806                 val.info1.flags       = (enum spoolss_FormFlags) IVAL(enum_values[i].data->data, 28);
2807
2808                 info[i + num_builtin] = val;
2809         }
2810
2811         *pnum_info = num_builtin + num_values;
2812         if (pinfo) {
2813                 *pinfo = talloc_move(mem_ctx, &info);
2814         }
2815
2816 done:
2817         if (is_valid_policy_hnd(&key_hnd)) {
2818                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2819         }
2820         if (is_valid_policy_hnd(&hive_hnd)) {
2821                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2822         }
2823
2824         TALLOC_FREE(enum_values);
2825         TALLOC_FREE(tmp_ctx);
2826         return result;
2827 }
2828
2829 WERROR winreg_printer_deleteform1(TALLOC_CTX *mem_ctx,
2830                                   struct dcerpc_binding_handle *winreg_handle,
2831                                   const char *form_name)
2832 {
2833         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2834         struct policy_handle hive_hnd, key_hnd;
2835         struct winreg_String wvalue = { 0, };
2836         uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
2837         uint32_t i;
2838         WERROR result = WERR_OK;
2839         WERROR ignore;
2840         NTSTATUS status;
2841         TALLOC_CTX *tmp_ctx;
2842
2843         for (i = 0; i < num_builtin; i++) {
2844                 if (strequal(builtin_forms1[i].form_name, form_name)) {
2845                         return WERR_INVALID_PARAMETER;
2846                 }
2847         }
2848
2849         tmp_ctx = talloc_stackframe();
2850         if (tmp_ctx == NULL) {
2851                 return WERR_NOMEM;
2852         }
2853
2854         ZERO_STRUCT(hive_hnd);
2855         ZERO_STRUCT(key_hnd);
2856
2857         result = winreg_printer_openkey(tmp_ctx,
2858                                         winreg_handle,
2859                                         TOP_LEVEL_CONTROL_FORMS_KEY,
2860                                         "",
2861                                         false,
2862                                         access_mask,
2863                                         &hive_hnd,
2864                                         &key_hnd);
2865         if (!W_ERROR_IS_OK(result)) {
2866                 DEBUG(0, ("winreg_printer_deleteform1: Could not open key %s: %s\n",
2867                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2868                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2869                         result = WERR_INVALID_FORM_NAME;
2870                 }
2871                 goto done;
2872         }
2873
2874         wvalue.name = form_name;
2875         status = dcerpc_winreg_DeleteValue(winreg_handle,
2876                                            tmp_ctx,
2877                                            &key_hnd,
2878                                            wvalue,
2879                                            &result);
2880         if (!NT_STATUS_IS_OK(status)) {
2881                 /* If the value doesn't exist, return WERR_INVALID_FORM_NAME */
2882                 DEBUG(0, ("winreg_printer_delteform1: Could not delete value %s: %s\n",
2883                           wvalue.name, nt_errstr(status)));
2884                 result = ntstatus_to_werror(status);
2885                 goto done;
2886         }
2887
2888         if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2889                 result = WERR_INVALID_FORM_NAME;
2890         }
2891
2892 done:
2893         if (is_valid_policy_hnd(&key_hnd)) {
2894                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2895         }
2896         if (is_valid_policy_hnd(&hive_hnd)) {
2897                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2898         }
2899
2900         TALLOC_FREE(tmp_ctx);
2901         return result;
2902 }
2903
2904 WERROR winreg_printer_setform1(TALLOC_CTX *mem_ctx,
2905                                struct dcerpc_binding_handle *winreg_handle,
2906                                const char *form_name,
2907                                struct spoolss_AddFormInfo1 *form)
2908 {
2909         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2910         struct policy_handle hive_hnd = { 0, };
2911         struct policy_handle key_hnd = { 0, };
2912         struct winreg_String wvalue = { 0, };
2913         DATA_BLOB blob;
2914         uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
2915         uint32_t i;
2916         WERROR result;
2917         NTSTATUS status;
2918         TALLOC_CTX *tmp_ctx = NULL;
2919
2920         for (i = 0; i < num_builtin; i++) {
2921                 if (strequal(builtin_forms1[i].form_name, form->form_name)) {
2922                         result = WERR_INVALID_PARAM;
2923                         goto done;
2924                 }
2925         }
2926
2927         tmp_ctx = talloc_stackframe();
2928         if (tmp_ctx == NULL) {
2929                 return WERR_NOMEM;
2930         }
2931
2932         ZERO_STRUCT(hive_hnd);
2933         ZERO_STRUCT(key_hnd);
2934
2935         result = winreg_printer_openkey(tmp_ctx,
2936                                         winreg_handle,
2937                                         TOP_LEVEL_CONTROL_FORMS_KEY,
2938                                         "",
2939                                         true,
2940                                         access_mask,
2941                                         &hive_hnd,
2942                                         &key_hnd);
2943         if (!W_ERROR_IS_OK(result)) {
2944                 DEBUG(0, ("winreg_printer_setform1: Could not open key %s: %s\n",
2945                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2946                 goto done;
2947         }
2948
2949         /* If form_name != form->form_name then we renamed the form */
2950         if (strequal(form_name, form->form_name)) {
2951                 result = winreg_printer_deleteform1(tmp_ctx, winreg_handle,
2952                                                     form_name);
2953                 if (!W_ERROR_IS_OK(result)) {
2954                         DEBUG(0, ("winreg_printer_setform1: Could not open key %s: %s\n",
2955                                   TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2956                         goto done;
2957                 }
2958         }
2959
2960         wvalue.name = form->form_name;
2961
2962         blob = data_blob_talloc(tmp_ctx, NULL, 32);
2963         SIVAL(blob.data,  0, form->size.width);
2964         SIVAL(blob.data,  4, form->size.height);
2965         SIVAL(blob.data,  8, form->area.left);
2966         SIVAL(blob.data, 12, form->area.top);
2967         SIVAL(blob.data, 16, form->area.right);
2968         SIVAL(blob.data, 20, form->area.bottom);
2969         SIVAL(blob.data, 24, 42);
2970         SIVAL(blob.data, 28, form->flags);
2971
2972         status = dcerpc_winreg_SetValue(winreg_handle,
2973                                         tmp_ctx,
2974                                         &key_hnd,
2975                                         wvalue,
2976                                         REG_BINARY,
2977                                         blob.data,
2978                                         blob.length,
2979                                         &result);
2980         if (!NT_STATUS_IS_OK(status)) {
2981                 DEBUG(0, ("winreg_printer_setform1: Could not set value %s: %s\n",
2982                           wvalue.name, nt_errstr(status)));
2983                 result = ntstatus_to_werror(status);
2984         }
2985
2986 done:
2987         if (winreg_handle != NULL) {
2988                 WERROR ignore;
2989
2990                 if (is_valid_policy_hnd(&key_hnd)) {
2991                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2992                 }
2993                 if (is_valid_policy_hnd(&hive_hnd)) {
2994                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2995                 }
2996         }
2997
2998         TALLOC_FREE(tmp_ctx);
2999         return result;
3000 }
3001
3002 WERROR winreg_printer_getform1(TALLOC_CTX *mem_ctx,
3003                                struct dcerpc_binding_handle *winreg_handle,
3004                                const char *form_name,
3005                                struct spoolss_FormInfo1 *r)
3006 {
3007         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3008         struct policy_handle hive_hnd, key_hnd;
3009         struct winreg_String wvalue;
3010         enum winreg_Type type_in = REG_NONE;
3011         uint8_t *data_in = NULL;
3012         uint32_t data_in_size = 0;
3013         uint32_t value_len = 0;
3014         uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
3015         uint32_t i;
3016         WERROR result;
3017         WERROR ignore;
3018         NTSTATUS status;
3019         TALLOC_CTX *tmp_ctx;
3020
3021         /* check builtin forms first */
3022         for (i = 0; i < num_builtin; i++) {
3023                 if (strequal(builtin_forms1[i].form_name, form_name)) {
3024                         *r = builtin_forms1[i];
3025                         return WERR_OK;
3026                 }
3027         }
3028
3029         tmp_ctx = talloc_stackframe();
3030         if (tmp_ctx == NULL) {
3031                 return WERR_NOMEM;
3032         }
3033
3034         ZERO_STRUCT(hive_hnd);
3035         ZERO_STRUCT(key_hnd);
3036
3037         result = winreg_printer_openkey(tmp_ctx,
3038                                         winreg_handle,
3039                                         TOP_LEVEL_CONTROL_FORMS_KEY,
3040                                         "",
3041                                         true,
3042                                         access_mask,
3043                                         &hive_hnd,
3044                                         &key_hnd);
3045         if (!W_ERROR_IS_OK(result)) {
3046                 DEBUG(2, ("winreg_printer_getform1: Could not open key %s: %s\n",
3047                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
3048                 goto done;
3049         }
3050
3051         wvalue.name = form_name;
3052
3053         /*
3054          * call QueryValue once with data == NULL to get the
3055          * needed memory size to be allocated, then allocate
3056          * data buffer and call again.
3057          */
3058         status = dcerpc_winreg_QueryValue(winreg_handle,
3059                                           tmp_ctx,
3060                                           &key_hnd,
3061                                           &wvalue,
3062                                           &type_in,
3063                                           NULL,
3064                                           &data_in_size,
3065                                           &value_len,
3066                                           &result);
3067         if (!NT_STATUS_IS_OK(status)) {
3068                 DEBUG(0, ("winreg_printer_getform1: Could not query value %s: %s\n",
3069                           wvalue.name, nt_errstr(status)));
3070                 result = ntstatus_to_werror(status);
3071                 goto done;
3072         }
3073         if (!W_ERROR_IS_OK(result)) {
3074                 goto done;
3075         }
3076
3077         data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
3078         if (data_in == NULL) {
3079                 result = WERR_NOMEM;
3080                 goto done;
3081         }
3082         value_len = 0;
3083
3084         status = dcerpc_winreg_QueryValue(winreg_handle,
3085                                           tmp_ctx,
3086                                           &key_hnd,
3087                                           &wvalue,
3088                                           &type_in,
3089                                           data_in,
3090                                           &data_in_size,
3091                                           &value_len,
3092                                           &result);
3093         if (!NT_STATUS_IS_OK(status)) {
3094                 DEBUG(0, ("winreg_printer_getform1: Could not query value %s: %s\n",
3095                           wvalue.name, nt_errstr(status)));
3096                 result = ntstatus_to_werror(status);
3097                 goto done;
3098         }
3099         if (!W_ERROR_IS_OK(result)) {
3100                 goto done;
3101         }
3102
3103         r->form_name = talloc_strdup(mem_ctx, form_name);
3104         if (r->form_name == NULL) {
3105                 result = WERR_NOMEM;
3106                 goto done;
3107         }
3108
3109         r->size.width  = IVAL(data_in,  0);
3110         r->size.height = IVAL(data_in,  4);
3111         r->area.left   = IVAL(data_in,  8);
3112         r->area.top    = IVAL(data_in, 12);
3113         r->area.right  = IVAL(data_in, 16);
3114         r->area.bottom = IVAL(data_in, 20);
3115         /* skip index    IVAL(data_in, 24)));*/
3116         r->flags       = (enum spoolss_FormFlags) IVAL(data_in, 28);
3117
3118         result = WERR_OK;
3119 done:
3120         if (is_valid_policy_hnd(&key_hnd)) {
3121                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3122         }
3123         if (is_valid_policy_hnd(&hive_hnd)) {
3124                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3125         }
3126
3127         TALLOC_FREE(tmp_ctx);
3128         return result;
3129 }
3130
3131 WERROR winreg_add_driver(TALLOC_CTX *mem_ctx,
3132                          struct dcerpc_binding_handle *winreg_handle,
3133                          struct spoolss_AddDriverInfoCtr *r,
3134                          const char **driver_name,
3135                          uint32_t *driver_version)
3136 {
3137         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3138         struct policy_handle hive_hnd, key_hnd;
3139         struct spoolss_DriverInfo8 info8;
3140         TALLOC_CTX *tmp_ctx = NULL;
3141         NTSTATUS status;
3142         WERROR result;
3143
3144         ZERO_STRUCT(hive_hnd);
3145         ZERO_STRUCT(key_hnd);
3146         ZERO_STRUCT(info8);
3147
3148         if (!driver_info_ctr_to_info8(r, &info8)) {
3149                 result = WERR_INVALID_PARAMETER;
3150                 goto done;
3151         }
3152
3153         tmp_ctx = talloc_stackframe();
3154         if (tmp_ctx == NULL) {
3155                 return WERR_NOMEM;
3156         }
3157
3158         result = winreg_printer_opendriver(tmp_ctx,
3159                                            winreg_handle,
3160                                            info8.driver_name,
3161                                            info8.architecture,
3162                                            info8.version,
3163                                            access_mask, true,
3164                                            &hive_hnd,
3165                                            &key_hnd);
3166         if (!W_ERROR_IS_OK(result)) {
3167                 DEBUG(0, ("winreg_add_driver: "
3168                           "Could not open driver key (%s,%s,%d): %s\n",
3169                           info8.driver_name, info8.architecture,
3170                           info8.version, win_errstr(result)));
3171                 goto done;
3172         }
3173
3174         /* TODO: "Attributes" ? */
3175
3176         status = dcerpc_winreg_set_dword(tmp_ctx,
3177                                          winreg_handle,
3178                                          &key_hnd,
3179                                          "Version",
3180                                          info8.version,
3181                                          &result);
3182         if (!NT_STATUS_IS_OK(status)) {
3183                 result = ntstatus_to_werror(status);
3184         }
3185         if (!W_ERROR_IS_OK(result)) {
3186                 goto done;
3187         }
3188
3189         status = dcerpc_winreg_set_sz(tmp_ctx,
3190                                       winreg_handle,
3191                                       &key_hnd,
3192                                       "Driver",
3193                                       info8.driver_path,
3194                                       &result);
3195         if (!NT_STATUS_IS_OK(status)) {
3196                 result = ntstatus_to_werror(status);
3197         }
3198         if (!W_ERROR_IS_OK(result)) {
3199                 goto done;
3200         }
3201
3202         status = dcerpc_winreg_set_sz(tmp_ctx,
3203                                       winreg_handle,
3204                                       &key_hnd,
3205                                       "Data File",
3206                                       info8.data_file,
3207                                       &result);
3208         if (!NT_STATUS_IS_OK(status)) {
3209                 result = ntstatus_to_werror(status);
3210         }
3211         if (!W_ERROR_IS_OK(result)) {
3212                 goto done;
3213         }
3214
3215         status = dcerpc_winreg_set_sz(tmp_ctx,
3216                                       winreg_handle,
3217                                       &key_hnd,
3218                                       "Configuration File",
3219                                       info8.config_file,
3220                                       &result);
3221         if (!NT_STATUS_IS_OK(status)) {
3222                 result = ntstatus_to_werror(status);
3223         }
3224         if (!W_ERROR_IS_OK(result)) {
3225                 goto done;
3226         }
3227
3228         status = dcerpc_winreg_set_sz(tmp_ctx,
3229                                       winreg_handle,
3230                                       &key_hnd,
3231                                       "Help File",
3232                                       info8.help_file,
3233                                       &result);
3234         if (!NT_STATUS_IS_OK(status)) {
3235                 result = ntstatus_to_werror(status);
3236         }
3237         if (!W_ERROR_IS_OK(result)) {
3238                 goto done;
3239         }
3240
3241         status = dcerpc_winreg_set_multi_sz(tmp_ctx,
3242                                             winreg_handle,
3243                                             &key_hnd,
3244                                             "Dependent Files",
3245                                             info8.dependent_files,
3246                                             &result);
3247         if (!NT_STATUS_IS_OK(status)) {
3248                 result = ntstatus_to_werror(status);
3249         }
3250         if (!W_ERROR_IS_OK(result)) {
3251                 goto done;
3252         }
3253
3254         status = dcerpc_winreg_set_sz(tmp_ctx,
3255                                       winreg_handle,
3256                                       &key_hnd,
3257                                       "Monitor",
3258                                       info8.monitor_name,
3259                                       &result);
3260         if (!NT_STATUS_IS_OK(status)) {
3261                 result = ntstatus_to_werror(status);
3262         }
3263         if (!W_ERROR_IS_OK(result)) {
3264                 goto done;
3265         }
3266
3267         status = dcerpc_winreg_set_sz(tmp_ctx,
3268                                       winreg_handle,
3269                                       &key_hnd,
3270                                       "Datatype",
3271                                       info8.default_datatype,
3272                                       &result);
3273         if (!NT_STATUS_IS_OK(status)) {
3274                 result = ntstatus_to_werror(status);
3275         }
3276         if (!W_ERROR_IS_OK(result)) {
3277                 goto done;
3278         }
3279
3280         status = dcerpc_winreg_set_multi_sz(tmp_ctx,
3281                                             winreg_handle,
3282                                             &key_hnd, "Previous Names",
3283                                             info8.previous_names,
3284                                             &result);
3285         if (!NT_STATUS_IS_OK(status)) {
3286                 result = ntstatus_to_werror(status);
3287         }
3288         if (!W_ERROR_IS_OK(result)) {
3289                 goto done;
3290         }
3291
3292         result = winreg_printer_write_date(tmp_ctx, winreg_handle,
3293                                            &key_hnd, "DriverDate",
3294                                            info8.driver_date);
3295         if (!W_ERROR_IS_OK(result)) {
3296                 goto done;
3297         }
3298
3299         result = winreg_printer_write_ver(tmp_ctx, winreg_handle,
3300                                           &key_hnd, "DriverVersion",
3301                                           info8.driver_version);
3302         if (!W_ERROR_IS_OK(result)) {
3303                 goto done;
3304         }
3305
3306         status = dcerpc_winreg_set_sz(tmp_ctx,
3307                                       winreg_handle,
3308                                       &key_hnd,
3309                                       "Manufacturer",
3310                                       info8.manufacturer_name,
3311                                       &result);
3312         if (!NT_STATUS_IS_OK(status)) {
3313                 result = ntstatus_to_werror(status);
3314         }
3315         if (!W_ERROR_IS_OK(result)) {
3316                 goto done;
3317         }
3318
3319         status = dcerpc_winreg_set_sz(tmp_ctx,
3320                                       winreg_handle,
3321                                       &key_hnd,
3322                                       "OEM URL",
3323                                       info8.manufacturer_url,
3324                                       &result);
3325         if (!NT_STATUS_IS_OK(status)) {
3326                 result = ntstatus_to_werror(status);
3327         }
3328         if (!W_ERROR_IS_OK(result)) {
3329                 goto done;
3330         }
3331
3332         status = dcerpc_winreg_set_sz(tmp_ctx,
3333                                       winreg_handle,
3334                                       &key_hnd,
3335                                       "HardwareID",
3336                                       info8.hardware_id,
3337                                       &result);
3338         if (!NT_STATUS_IS_OK(status)) {
3339                 result = ntstatus_to_werror(status);
3340         }
3341         if (!W_ERROR_IS_OK(result)) {
3342                 goto done;
3343         }
3344
3345         status = dcerpc_winreg_set_sz(tmp_ctx,
3346                                       winreg_handle,
3347                                       &key_hnd,
3348                                       "Provider",
3349                                       info8.provider,
3350                                       &result);
3351         if (!NT_STATUS_IS_OK(status)) {
3352                 result = ntstatus_to_werror(status);
3353         }
3354         if (!W_ERROR_IS_OK(result)) {
3355                 goto done;
3356         }
3357
3358         status = dcerpc_winreg_set_sz(tmp_ctx,
3359                                       winreg_handle,
3360                                       &key_hnd,
3361                                       "Print Processor",
3362                                       info8.print_processor,
3363                                       &result);
3364         if (!NT_STATUS_IS_OK(status)) {
3365                 result = ntstatus_to_werror(status);
3366         }
3367         if (!W_ERROR_IS_OK(result)) {
3368                 goto done;
3369         }
3370
3371         status = dcerpc_winreg_set_sz(tmp_ctx,
3372                                       winreg_handle,
3373                                       &key_hnd,
3374                                       "VendorSetup",
3375                                       info8.vendor_setup,
3376                                       &result);
3377         if (!NT_STATUS_IS_OK(status)) {
3378                 result = ntstatus_to_werror(status);
3379         }
3380         if (!W_ERROR_IS_OK(result)) {
3381                 goto done;
3382         }
3383
3384         status = dcerpc_winreg_set_multi_sz(tmp_ctx,
3385                                             winreg_handle,
3386                                             &key_hnd,
3387                                             "Color Profiles",
3388                                             info8.color_profiles,
3389                                             &result);
3390         if (!NT_STATUS_IS_OK(status)) {
3391                 result = ntstatus_to_werror(status);
3392         }
3393         if (!W_ERROR_IS_OK(result)) {
3394                 goto done;
3395         }
3396
3397         status = dcerpc_winreg_set_sz(tmp_ctx,
3398                                       winreg_handle,
3399                                       &key_hnd,
3400                                       "InfPath",
3401                                       info8.inf_path,
3402                                       &result);
3403         if (!NT_STATUS_IS_OK(status)) {
3404                 result = ntstatus_to_werror(status);
3405         }
3406         if (!W_ERROR_IS_OK(result)) {
3407                 goto done;
3408         }
3409
3410         status = dcerpc_winreg_set_dword(tmp_ctx,
3411                                          winreg_handle,
3412                                          &key_hnd,
3413                                          "PrinterDriverAttributes",
3414                                          info8.printer_driver_attributes,
3415                                          &result);
3416         if (!NT_STATUS_IS_OK(status)) {
3417                 result = ntstatus_to_werror(status);
3418         }
3419         if (!W_ERROR_IS_OK(result)) {
3420                 goto done;
3421         }
3422
3423         status = dcerpc_winreg_set_multi_sz(tmp_ctx,
3424                                             winreg_handle,
3425                                             &key_hnd,
3426                                             "CoreDependencies",
3427                                             info8.core_driver_dependencies,
3428                                             &result);
3429         if (!NT_STATUS_IS_OK(status)) {
3430                 result = ntstatus_to_werror(status);
3431         }
3432         if (!W_ERROR_IS_OK(result)) {
3433                 goto done;
3434         }
3435
3436         result = winreg_printer_write_date(tmp_ctx, winreg_handle,
3437                                            &key_hnd, "MinInboxDriverVerDate",
3438                                            info8.min_inbox_driver_ver_date);
3439         if (!W_ERROR_IS_OK(result)) {
3440                 goto done;
3441         }
3442
3443         result = winreg_printer_write_ver(tmp_ctx, winreg_handle, &key_hnd,
3444                                           "MinInboxDriverVerVersion",
3445                                           info8.min_inbox_driver_ver_version);
3446         if (!W_ERROR_IS_OK(result)) {
3447                 goto done;
3448         }
3449
3450         *driver_name = info8.driver_name;
3451         *driver_version = info8.version;
3452         result = WERR_OK;
3453 done:
3454         if (winreg_handle != NULL) {
3455                 WERROR ignore;
3456
3457                 if (is_valid_policy_hnd(&key_hnd)) {
3458                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3459                 }
3460                 if (is_valid_policy_hnd(&hive_hnd)) {
3461                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3462                 }
3463         }
3464
3465         TALLOC_FREE(tmp_ctx);
3466         return result;
3467 }
3468
3469 WERROR winreg_get_driver(TALLOC_CTX *mem_ctx,
3470                          struct dcerpc_binding_handle *winreg_handle,
3471                          const char *architecture,
3472                          const char *driver_name,
3473                          uint32_t driver_version,
3474                          struct spoolss_DriverInfo8 **_info8)
3475 {
3476         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3477         struct policy_handle hive_hnd, key_hnd;
3478         struct spoolss_DriverInfo8 i8, *info8;
3479         struct spoolss_PrinterEnumValues *enum_values = NULL;
3480         struct spoolss_PrinterEnumValues *v;
3481         uint32_t num_values = 0;
3482         TALLOC_CTX *tmp_ctx;
3483         WERROR result;
3484         NTSTATUS status;
3485         uint32_t i;
3486         const char **enum_names = NULL;
3487         enum winreg_Type *enum_types = NULL;
3488         DATA_BLOB *enum_data_blobs = NULL;
3489
3490         ZERO_STRUCT(hive_hnd);
3491         ZERO_STRUCT(key_hnd);
3492         ZERO_STRUCT(i8);
3493
3494         tmp_ctx = talloc_stackframe();
3495         if (tmp_ctx == NULL) {
3496                 return WERR_NOMEM;
3497         }
3498
3499         if (driver_version == DRIVER_ANY_VERSION) {
3500                 /* look for Win2k first and then for NT4 */
3501                 result = winreg_printer_opendriver(tmp_ctx,
3502                                                    winreg_handle,
3503                                                    driver_name,
3504                                                    architecture,
3505                                                    3,
3506                                                    access_mask, false,
3507                                                    &hive_hnd,
3508                                                    &key_hnd);
3509                 if (!W_ERROR_IS_OK(result)) {
3510                         result = winreg_printer_opendriver(tmp_ctx,
3511                                                            winreg_handle,
3512                                                            driver_name,
3513                                                            architecture,
3514                                                            2,
3515                                                            access_mask, false,
3516                                                            &hive_hnd,
3517                                                            &key_hnd);
3518                 }
3519         } else {
3520                 /* ok normal case */
3521                 result = winreg_printer_opendriver(tmp_ctx,
3522                                                    winreg_handle,
3523                                                    driver_name,
3524                                                    architecture,
3525                                                    driver_version,
3526                                                    access_mask, false,
3527                                                    &hive_hnd,
3528                                                    &key_hnd);
3529         }
3530         if (!W_ERROR_IS_OK(result)) {
3531                 DEBUG(5, ("winreg_get_driver: "
3532                           "Could not open driver key (%s,%s,%d): %s\n",
3533                           driver_name, architecture,
3534                           driver_version, win_errstr(result)));
3535                 goto done;
3536         }
3537
3538         status = dcerpc_winreg_enumvals(tmp_ctx,
3539                                         winreg_handle,
3540                                         &key_hnd,
3541                                         &num_values,
3542                                         &enum_names,
3543                                         &enum_types,
3544                                         &enum_data_blobs,
3545                                         &result);
3546         if (!NT_STATUS_IS_OK(status)){
3547                 result = ntstatus_to_werror(status);
3548         }
3549
3550         if (!W_ERROR_IS_OK(result)) {
3551                 DEBUG(0, ("winreg_get_driver: "
3552                           "Could not enumerate values for (%s,%s,%d): %s\n",
3553                           driver_name, architecture,
3554                           driver_version, win_errstr(result)));
3555                 goto done;
3556         }
3557
3558         enum_values = talloc_zero_array(tmp_ctx,
3559                                         struct spoolss_PrinterEnumValues,
3560                                         num_values);
3561         if (enum_values == NULL){
3562                 result = WERR_NOMEM;
3563                 goto done;
3564         }
3565
3566         for (i = 0; i < num_values; i++){
3567                 enum_values[i].value_name = enum_names[i];
3568                 enum_values[i].value_name_len = strlen_m_term(enum_names[i]) * 2;
3569                 enum_values[i].type = enum_types[i];
3570                 enum_values[i].data_length = enum_data_blobs[i].length;
3571                 enum_values[i].data = NULL;
3572                 if (enum_values[i].data_length != 0){
3573                         enum_values[i].data = &enum_data_blobs[i];
3574                 }
3575         }
3576
3577         info8 = talloc_zero(tmp_ctx, struct spoolss_DriverInfo8);
3578         if (info8 == NULL) {
3579                 result = WERR_NOMEM;
3580                 goto done;
3581         }
3582
3583         info8->driver_name = talloc_strdup(info8, driver_name);
3584         if (info8->driver_name == NULL) {
3585                 result = WERR_NOMEM;
3586                 goto done;
3587         }
3588
3589         info8->architecture = talloc_strdup(info8, architecture);
3590         if (info8->architecture == NULL) {
3591                 result = WERR_NOMEM;
3592                 goto done;
3593         }
3594
3595         result = WERR_OK;
3596
3597         for (i = 0; i < num_values; i++) {
3598                 const char *tmp_str;
3599                 uint32_t tmp = 0;
3600
3601                 v = &enum_values[i];
3602
3603                 result = winreg_enumval_to_dword(info8, v,
3604                                                  "Version",
3605                                                  &tmp);
3606                 if (W_ERROR_IS_OK(result)) {
3607                         info8->version = (enum spoolss_DriverOSVersion) tmp;
3608                 }
3609                 CHECK_ERROR(result);
3610
3611                 result = winreg_enumval_to_sz(info8, v,
3612                                               "Driver",
3613                                               &info8->driver_path);
3614                 CHECK_ERROR(result);
3615
3616                 result = winreg_enumval_to_sz(info8, v,
3617                                               "Data File",
3618                                               &info8->data_file);
3619                 CHECK_ERROR(result);
3620
3621                 result = winreg_enumval_to_sz(info8, v,
3622                                               "Configuration File",
3623                                               &info8->config_file);
3624                 CHECK_ERROR(result);
3625
3626                 result = winreg_enumval_to_sz(info8, v,
3627                                               "Help File",
3628                                               &info8->help_file);
3629                 CHECK_ERROR(result);
3630
3631                 result = winreg_enumval_to_multi_sz(info8, v,
3632                                                     "Dependent Files",
3633                                                     &info8->dependent_files);
3634                 CHECK_ERROR(result);
3635
3636                 result = winreg_enumval_to_sz(info8, v,
3637                                               "Monitor",
3638                                               &info8->monitor_name);
3639                 CHECK_ERROR(result);
3640
3641                 result = winreg_enumval_to_sz(info8, v,
3642                                               "Datatype",
3643                                               &info8->default_datatype);
3644                 CHECK_ERROR(result);
3645
3646                 result = winreg_enumval_to_multi_sz(info8, v,
3647                                                     "Previous Names",
3648                                                     &info8->previous_names);
3649                 CHECK_ERROR(result);
3650
3651                 result = winreg_enumval_to_sz(info8, v,
3652                                               "DriverDate",
3653                                               &tmp_str);
3654                 if (W_ERROR_IS_OK(result)) {
3655                         result = winreg_printer_date_to_NTTIME(tmp_str,
3656                                                 &info8->driver_date);
3657                 }
3658                 CHECK_ERROR(result);
3659
3660                 result = winreg_enumval_to_sz(info8, v,
3661                                               "DriverVersion",
3662                                               &tmp_str);
3663                 if (W_ERROR_IS_OK(result)) {
3664                         result = winreg_printer_ver_to_dword(tmp_str,
3665                                                 &info8->driver_version);
3666                 }
3667                 CHECK_ERROR(result);
3668
3669                 result = winreg_enumval_to_sz(info8, v,
3670                                               "Manufacturer",
3671                                               &info8->manufacturer_name);
3672                 CHECK_ERROR(result);
3673
3674                 result = winreg_enumval_to_sz(info8, v,
3675                                               "OEM URL",
3676                                               &info8->manufacturer_url);
3677                 CHECK_ERROR(result);
3678
3679                 result = winreg_enumval_to_sz(info8, v,
3680                                               "HardwareID",
3681                                               &info8->hardware_id);
3682                 CHECK_ERROR(result);
3683
3684                 result = winreg_enumval_to_sz(info8, v,
3685                                               "Provider",
3686                                               &info8->provider);
3687                 CHECK_ERROR(result);
3688
3689                 result = winreg_enumval_to_sz(info8, v,
3690                                               "Print Processor",
3691                                               &info8->print_processor);
3692                 CHECK_ERROR(result);
3693
3694                 result = winreg_enumval_to_sz(info8, v,
3695                                               "VendorSetup",
3696                                               &info8->vendor_setup);
3697                 CHECK_ERROR(result);
3698
3699                 result = winreg_enumval_to_multi_sz(info8, v,
3700                                                     "Color Profiles",
3701                                                     &info8->color_profiles);
3702                 CHECK_ERROR(result);
3703
3704                 result = winreg_enumval_to_sz(info8, v,
3705                                               "InfPath",
3706                                               &info8->inf_path);
3707                 CHECK_ERROR(result);
3708
3709                 result = winreg_enumval_to_dword(info8, v,
3710                                                  "PrinterDriverAttributes",
3711                                                  &info8->printer_driver_attributes);
3712                 CHECK_ERROR(result);
3713
3714                 result = winreg_enumval_to_multi_sz(info8, v,
3715                                                     "CoreDependencies",
3716                                                     &info8->core_driver_dependencies);
3717                 CHECK_ERROR(result);
3718
3719                 result = winreg_enumval_to_sz(info8, v,
3720                                               "MinInboxDriverVerDate",
3721                                               &tmp_str);
3722                 if (W_ERROR_IS_OK(result)) {
3723                         result = winreg_printer_date_to_NTTIME(tmp_str,
3724                                         &info8->min_inbox_driver_ver_date);
3725                 }
3726                 CHECK_ERROR(result);
3727
3728                 result = winreg_enumval_to_sz(info8, v,
3729                                               "MinInboxDriverVerVersion",
3730                                               &tmp_str);
3731                 if (W_ERROR_IS_OK(result)) {
3732                         result = winreg_printer_ver_to_dword(tmp_str,
3733                                         &info8->min_inbox_driver_ver_version);
3734                 }
3735                 CHECK_ERROR(result);
3736         }
3737
3738         if (!W_ERROR_IS_OK(result)) {
3739                 DEBUG(0, ("winreg_enumval_to_TYPE() failed "
3740                           "for %s: %s\n", v->value_name,
3741                           win_errstr(result)));
3742                 goto done;
3743         }
3744
3745         *_info8 = talloc_steal(mem_ctx, info8);
3746         result = WERR_OK;
3747 done:
3748         if (winreg_handle != NULL) {
3749                 WERROR ignore;
3750
3751                 if (is_valid_policy_hnd(&key_hnd)) {
3752                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3753                 }
3754                 if (is_valid_policy_hnd(&hive_hnd)) {
3755                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3756                 }
3757         }
3758
3759         TALLOC_FREE(tmp_ctx);
3760         return result;
3761 }
3762
3763 WERROR winreg_del_driver(TALLOC_CTX *mem_ctx,
3764                          struct dcerpc_binding_handle *winreg_handle,
3765                          struct spoolss_DriverInfo8 *info8,
3766                          uint32_t version)
3767 {
3768         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3769         struct policy_handle hive_hnd, key_hnd;
3770         TALLOC_CTX *tmp_ctx;
3771         char *key_name;
3772         WERROR result;
3773         NTSTATUS status;
3774
3775         ZERO_STRUCT(hive_hnd);
3776         ZERO_STRUCT(key_hnd);
3777
3778         tmp_ctx = talloc_stackframe();
3779         if (tmp_ctx == NULL) {
3780                 return WERR_NOMEM;
3781         }
3782
3783         /* test that the key exists */
3784         result = winreg_printer_opendriver(tmp_ctx,
3785                                            winreg_handle,
3786                                            info8->driver_name,
3787                                            info8->architecture,
3788                                            version,
3789                                            access_mask, false,
3790                                            &hive_hnd,
3791                                            &key_hnd);
3792         if (!W_ERROR_IS_OK(result)) {
3793                 /* key doesn't exist */
3794                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
3795                         result = WERR_OK;
3796                         goto done;
3797                 }
3798
3799                 DEBUG(5, ("winreg_del_driver: "
3800                           "Could not open driver (%s,%s,%u): %s\n",
3801                           info8->driver_name, info8->architecture,
3802                           version, win_errstr(result)));
3803                 goto done;
3804         }
3805
3806
3807         if (is_valid_policy_hnd(&key_hnd)) {
3808                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &result);
3809         }
3810
3811         key_name = talloc_asprintf(tmp_ctx,
3812                                    "%s\\Environments\\%s\\Drivers\\Version-%u\\%s",
3813                                    TOP_LEVEL_CONTROL_KEY,
3814                                    info8->architecture, version,
3815                                    info8->driver_name);
3816         if (key_name == NULL) {
3817                 result = WERR_NOMEM;
3818                 goto done;
3819         }
3820
3821         status = dcerpc_winreg_delete_subkeys_recursive(tmp_ctx,
3822                                                         winreg_handle,
3823                                                         &hive_hnd,
3824                                                         access_mask,
3825                                                         key_name,
3826                                                         &result);
3827
3828         if (!NT_STATUS_IS_OK(status)){
3829                 DEBUG(0, ("winreg_del_driver: "
3830                           "Could not open driver (%s,%s,%u): %s\n",
3831                           info8->driver_name, info8->architecture,
3832                           version, nt_errstr(status)));
3833                 goto done;
3834         }
3835
3836         if (!W_ERROR_IS_OK(result)) {
3837                 DEBUG(0, ("winreg_del_driver: "
3838                           "Could not open driver (%s,%s,%u): %s\n",
3839                           info8->driver_name, info8->architecture,
3840                           version, win_errstr(result)));
3841                 goto done;
3842         }
3843
3844         result = WERR_OK;
3845 done:
3846         if (winreg_handle != NULL) {
3847                 WERROR ignore;
3848
3849                 if (is_valid_policy_hnd(&key_hnd)) {
3850                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3851                 }
3852                 if (is_valid_policy_hnd(&hive_hnd)) {
3853                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3854                 }
3855         }
3856
3857         TALLOC_FREE(tmp_ctx);
3858         return result;
3859 }
3860
3861 WERROR winreg_get_driver_list(TALLOC_CTX *mem_ctx,
3862                               struct dcerpc_binding_handle *winreg_handle,
3863                               const char *architecture,
3864                               uint32_t version,
3865                               uint32_t *num_drivers,
3866                               const char ***drivers_p)
3867 {
3868         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3869         struct policy_handle hive_hnd, key_hnd;
3870         const char **drivers;
3871         TALLOC_CTX *tmp_ctx;
3872         WERROR result;
3873         NTSTATUS status;
3874
3875         *num_drivers = 0;
3876         *drivers_p = NULL;
3877
3878         ZERO_STRUCT(hive_hnd);
3879         ZERO_STRUCT(key_hnd);
3880
3881         tmp_ctx = talloc_stackframe();
3882         if (tmp_ctx == NULL) {
3883                 return WERR_NOMEM;
3884         }
3885
3886         /* use NULL for the driver name so we open the key that is
3887          * parent of all drivers for this architecture and version */
3888         result = winreg_printer_opendriver(tmp_ctx,
3889                                            winreg_handle,
3890                                            NULL,
3891                                            architecture,
3892                                            version,
3893                                            access_mask, false,
3894                                            &hive_hnd,
3895                                            &key_hnd);
3896         if (!W_ERROR_IS_OK(result)) {
3897                 DEBUG(5, ("winreg_get_driver_list: "
3898                           "Could not open key (%s,%u): %s\n",
3899                           architecture, version, win_errstr(result)));
3900                 result = WERR_OK;
3901                 goto done;
3902         }
3903
3904         status = dcerpc_winreg_enum_keys(tmp_ctx,
3905                                          winreg_handle,
3906                                          &key_hnd,
3907                                          num_drivers,
3908                                          &drivers,
3909                                          &result);
3910         if (!NT_STATUS_IS_OK(status)) {
3911                 result = ntstatus_to_werror(status);
3912         }
3913         if (!W_ERROR_IS_OK(result)) {
3914                 DEBUG(0, ("winreg_get_driver_list: "
3915                           "Could not enumerate drivers for (%s,%u): %s\n",
3916                           architecture, version, win_errstr(result)));
3917                 goto done;
3918         }
3919
3920         *drivers_p = talloc_steal(mem_ctx, drivers);
3921
3922         result = WERR_OK;
3923 done:
3924         if (winreg_handle != NULL) {
3925                 WERROR ignore;
3926
3927                 if (is_valid_policy_hnd(&key_hnd)) {
3928                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
3929                 }
3930                 if (is_valid_policy_hnd(&hive_hnd)) {
3931                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
3932                 }
3933         }
3934
3935         TALLOC_FREE(tmp_ctx);
3936         return result;
3937 }