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