s3:lib: add utility function sid_check_is_for_passdb()
[kai/samba.git] / source3 / rpc_client / cli_winreg_spoolss.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *
4  *  SPOOLSS RPC Pipe server / winreg client routines
5  *
6  *  Copyright (c) 2010      Andreas Schneider <asn@samba.org>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "nt_printing.h"
24 #include "../librpc/gen_ndr/ndr_spoolss.h"
25 #include "../librpc/gen_ndr/ndr_winreg_c.h"
26 #include "../librpc/gen_ndr/ndr_security.h"
27 #include "secrets.h"
28 #include "../libcli/security/security.h"
29 #include "rpc_client/cli_winreg.h"
30 #include "../libcli/registry/util_reg.h"
31 #include "rpc_client/cli_winreg_spoolss.h"
32 #include "printing/nt_printing_os2.h"
33 #include "rpc_client/init_spoolss.h"
34
35 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
36 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
37 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
38 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
39
40 #define EMPTY_STRING ""
41
42 #define FILL_STRING(mem_ctx, in, out) \
43         do { \
44                 if (in && strlen(in)) { \
45                         out = talloc_strdup(mem_ctx, in); \
46                 } else { \
47                         out = talloc_strdup(mem_ctx, ""); \
48                 } \
49                 W_ERROR_HAVE_NO_MEMORY(out); \
50         } while (0);
51
52 #define CHECK_ERROR(result) \
53         if (W_ERROR_IS_OK(result)) continue; \
54         if (W_ERROR_EQUAL(result, WERR_NOT_FOUND)) result = WERR_OK; \
55         if (!W_ERROR_IS_OK(result)) break
56
57 /*        FLAGS,                NAME,                              with,   height,   left, top, right, bottom */
58 static const struct spoolss_FormInfo1 builtin_forms1[] = {
59         { SPOOLSS_FORM_BUILTIN, "Letter",                         {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
60         { SPOOLSS_FORM_BUILTIN, "Letter Small",                   {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
61         { SPOOLSS_FORM_BUILTIN, "Tabloid",                        {0x44368,0x696b8}, {0x0,0x0,0x44368,0x696b8} },
62         { SPOOLSS_FORM_BUILTIN, "Ledger",                         {0x696b8,0x44368}, {0x0,0x0,0x696b8,0x44368} },
63         { SPOOLSS_FORM_BUILTIN, "Legal",                          {0x34b5c,0x56d10}, {0x0,0x0,0x34b5c,0x56d10} },
64         { SPOOLSS_FORM_BUILTIN, "Statement",                      {0x221b4,0x34b5c}, {0x0,0x0,0x221b4,0x34b5c} },
65         { SPOOLSS_FORM_BUILTIN, "Executive",                      {0x2cf56,0x411cc}, {0x0,0x0,0x2cf56,0x411cc} },
66         { SPOOLSS_FORM_BUILTIN, "A3",                             {0x48828,0x668a0}, {0x0,0x0,0x48828,0x668a0} },
67         { SPOOLSS_FORM_BUILTIN, "A4",                             {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
68         { SPOOLSS_FORM_BUILTIN, "A4 Small",                       {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
69         { SPOOLSS_FORM_BUILTIN, "A5",                             {0x24220,0x33450}, {0x0,0x0,0x24220,0x33450} },
70         { SPOOLSS_FORM_BUILTIN, "B4 (JIS)",                       {0x3ebe8,0x58de0}, {0x0,0x0,0x3ebe8,0x58de0} },
71         { SPOOLSS_FORM_BUILTIN, "B5 (JIS)",                       {0x2c6f0,0x3ebe8}, {0x0,0x0,0x2c6f0,0x3ebe8} },
72         { SPOOLSS_FORM_BUILTIN, "Folio",                          {0x34b5c,0x509d8}, {0x0,0x0,0x34b5c,0x509d8} },
73         { SPOOLSS_FORM_BUILTIN, "Quarto",                         {0x347d8,0x43238}, {0x0,0x0,0x347d8,0x43238} },
74         { SPOOLSS_FORM_BUILTIN, "10x14",                          {0x3e030,0x56d10}, {0x0,0x0,0x3e030,0x56d10} },
75         { SPOOLSS_FORM_BUILTIN, "11x17",                          {0x44368,0x696b8}, {0x0,0x0,0x44368,0x696b8} },
76         { SPOOLSS_FORM_BUILTIN, "Note",                           {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
77         { SPOOLSS_FORM_BUILTIN, "Envelope #9",                    {0x18079,0x37091}, {0x0,0x0,0x18079,0x37091} },
78         { SPOOLSS_FORM_BUILTIN, "Envelope #10",                   {0x19947,0x3ae94}, {0x0,0x0,0x19947,0x3ae94} },
79         { SPOOLSS_FORM_BUILTIN, "Envelope #11",                   {0x1be7c,0x40565}, {0x0,0x0,0x1be7c,0x40565} },
80         { SPOOLSS_FORM_BUILTIN, "Envelope #12",                   {0x1d74a,0x44368}, {0x0,0x0,0x1d74a,0x44368} },
81         { SPOOLSS_FORM_BUILTIN, "Envelope #14",                   {0x1f018,0x47504}, {0x0,0x0,0x1f018,0x47504} },
82         { SPOOLSS_FORM_BUILTIN, "C size sheet",                   {0x696b8,0x886d0}, {0x0,0x0,0x696b8,0x886d0} },
83         { SPOOLSS_FORM_BUILTIN, "D size sheet",                   {0x886d0,0xd2d70}, {0x0,0x0,0x886d0,0xd2d70} },
84         { SPOOLSS_FORM_BUILTIN, "E size sheet",                   {0xd2d70,0x110da0},{0x0,0x0,0xd2d70,0x110da0} },
85         { SPOOLSS_FORM_BUILTIN, "Envelope DL",                    {0x1adb0,0x35b60}, {0x0,0x0,0x1adb0,0x35b60} },
86         { SPOOLSS_FORM_BUILTIN, "Envelope C5",                    {0x278d0,0x37e88}, {0x0,0x0,0x278d0,0x37e88} },
87         { SPOOLSS_FORM_BUILTIN, "Envelope C3",                    {0x4f1a0,0x6fd10}, {0x0,0x0,0x4f1a0,0x6fd10} },
88         { SPOOLSS_FORM_BUILTIN, "Envelope C4",                    {0x37e88,0x4f1a0}, {0x0,0x0,0x37e88,0x4f1a0} },
89         { SPOOLSS_FORM_BUILTIN, "Envelope C6",                    {0x1bd50,0x278d0}, {0x0,0x0,0x1bd50,0x278d0} },
90         { SPOOLSS_FORM_BUILTIN, "Envelope C65",                   {0x1bd50,0x37e88}, {0x0,0x0,0x1bd50,0x37e88} },
91         { SPOOLSS_FORM_BUILTIN, "Envelope B4",                    {0x3d090,0x562e8}, {0x0,0x0,0x3d090,0x562e8} },
92         { SPOOLSS_FORM_BUILTIN, "Envelope B5",                    {0x2af80,0x3d090}, {0x0,0x0,0x2af80,0x3d090} },
93         { SPOOLSS_FORM_BUILTIN, "Envelope B6",                    {0x2af80,0x1e848}, {0x0,0x0,0x2af80,0x1e848} },
94         { SPOOLSS_FORM_BUILTIN, "Envelope",                       {0x1adb0,0x38270}, {0x0,0x0,0x1adb0,0x38270} },
95         { SPOOLSS_FORM_BUILTIN, "Envelope Monarch",               {0x18079,0x2e824}, {0x0,0x0,0x18079,0x2e824} },
96         { SPOOLSS_FORM_BUILTIN, "6 3/4 Envelope",                 {0x167ab,0x284ec}, {0x0,0x0,0x167ab,0x284ec} },
97         { SPOOLSS_FORM_BUILTIN, "US Std Fanfold",                 {0x5c3e1,0x44368}, {0x0,0x0,0x5c3e1,0x44368} },
98         { SPOOLSS_FORM_BUILTIN, "German Std Fanfold",             {0x34b5c,0x4a6a0}, {0x0,0x0,0x34b5c,0x4a6a0} },
99         { SPOOLSS_FORM_BUILTIN, "German Legal Fanfold",           {0x34b5c,0x509d8}, {0x0,0x0,0x34b5c,0x509d8} },
100         { SPOOLSS_FORM_BUILTIN, "B4 (ISO)",                       {0x3d090,0x562e8}, {0x0,0x0,0x3d090,0x562e8} },
101         { SPOOLSS_FORM_BUILTIN, "Japanese Postcard",              {0x186a0,0x24220}, {0x0,0x0,0x186a0,0x24220} },
102         { SPOOLSS_FORM_BUILTIN, "9x11",                           {0x37cf8,0x44368}, {0x0,0x0,0x37cf8,0x44368} },
103         { SPOOLSS_FORM_BUILTIN, "10x11",                          {0x3e030,0x44368}, {0x0,0x0,0x3e030,0x44368} },
104         { SPOOLSS_FORM_BUILTIN, "15x11",                          {0x5d048,0x44368}, {0x0,0x0,0x5d048,0x44368} },
105         { SPOOLSS_FORM_BUILTIN, "Envelope Invite",                {0x35b60,0x35b60}, {0x0,0x0,0x35b60,0x35b60} },
106         { SPOOLSS_FORM_BUILTIN, "Reserved48",                     {0x1,0x1},         {0x0,0x0,0x1,0x1} },
107         { SPOOLSS_FORM_BUILTIN, "Reserved49",                     {0x1,0x1},         {0x0,0x0,0x1,0x1} },
108         { SPOOLSS_FORM_BUILTIN, "Letter Extra",                   {0x3ae94,0x4a6a0}, {0x0,0x0,0x3ae94,0x4a6a0} },
109         { SPOOLSS_FORM_BUILTIN, "Legal Extra",                    {0x3ae94,0x5d048}, {0x0,0x0,0x3ae94,0x5d048} },
110         { SPOOLSS_FORM_BUILTIN, "Tabloid Extra",                  {0x4a6a0,0x6f9f0}, {0x0,0x0,0x4a6a0,0x6f9f0} },
111         { SPOOLSS_FORM_BUILTIN, "A4 Extra",                       {0x397c2,0x4eb16}, {0x0,0x0,0x397c2,0x4eb16} },
112         { SPOOLSS_FORM_BUILTIN, "Letter Transverse",              {0x34b5c,0x44368}, {0x0,0x0,0x34b5c,0x44368} },
113         { SPOOLSS_FORM_BUILTIN, "A4 Transverse",                  {0x33450,0x48828}, {0x0,0x0,0x33450,0x48828} },
114         { SPOOLSS_FORM_BUILTIN, "Letter Extra Transverse",        {0x3ae94,0x4a6a0}, {0x0,0x0,0x3ae94,0x4a6a0} },
115         { SPOOLSS_FORM_BUILTIN, "Super A",                        {0x376b8,0x56ea0}, {0x0,0x0,0x376b8,0x56ea0} },
116         { SPOOLSS_FORM_BUILTIN, "Super B",                        {0x4a768,0x76e58}, {0x0,0x0,0x4a768,0x76e58} },
117         { SPOOLSS_FORM_BUILTIN, "Letter Plus",                    {0x34b5c,0x4eb16}, {0x0,0x0,0x34b5c,0x4eb16} },
118         { SPOOLSS_FORM_BUILTIN, "A4 Plus",                        {0x33450,0x50910}, {0x0,0x0,0x33450,0x50910} },
119         { SPOOLSS_FORM_BUILTIN, "A5 Transverse",                  {0x24220,0x33450}, {0x0,0x0,0x24220,0x33450} },
120         { SPOOLSS_FORM_BUILTIN, "B5 (JIS) Transverse",            {0x2c6f0,0x3ebe8}, {0x0,0x0,0x2c6f0,0x3ebe8} },
121         { SPOOLSS_FORM_BUILTIN, "A3 Extra",                       {0x4e9d0,0x6ca48}, {0x0,0x0,0x4e9d0,0x6ca48} },
122         { SPOOLSS_FORM_BUILTIN, "A5 Extra",                       {0x2a7b0,0x395f8}, {0x0,0x0,0x2a7b0,0x395f8} },
123         { SPOOLSS_FORM_BUILTIN, "B5 (ISO) Extra",                 {0x31128,0x43620}, {0x0,0x0,0x31128,0x43620} },
124         { SPOOLSS_FORM_BUILTIN, "A2",                             {0x668a0,0x91050}, {0x0,0x0,0x668a0,0x91050} },
125         { SPOOLSS_FORM_BUILTIN, "A3 Transverse",                  {0x48828,0x668a0}, {0x0,0x0,0x48828,0x668a0} },
126         { SPOOLSS_FORM_BUILTIN, "A3 Extra Transverse",            {0x4e9d0,0x6ca48}, {0x0,0x0,0x4e9d0,0x6ca48} },
127         { SPOOLSS_FORM_BUILTIN, "Japanese Double Postcard",       {0x30d40,0x24220}, {0x0,0x0,0x30d40,0x24220} },
128         { SPOOLSS_FORM_BUILTIN, "A6",                             {0x19a28,0x24220}, {0x0,0x0,0x19a28,0x24220} },
129         { SPOOLSS_FORM_BUILTIN, "Japan Envelope Kaku #2 Rotated", {0x510e0,0x3a980}, {0x0,0x0,0x510e0,0x3a980} },
130         { SPOOLSS_FORM_BUILTIN, "Japan Envelope Kaku #3 Rotated", {0x43a08,0x34bc0}, {0x0,0x0,0x43a08,0x34bc0} },
131         { SPOOLSS_FORM_BUILTIN, "Japan Envelope Chou #3 Rotated", {0x395f8,0x1d4c0}, {0x0,0x0,0x395f8,0x1d4c0} },
132         { SPOOLSS_FORM_BUILTIN, "Japan Envelope Chou #4 Rotated", {0x320c8,0x15f90}, {0x0,0x0,0x320c8,0x15f90} },
133         { SPOOLSS_FORM_BUILTIN, "Letter Rotated",                 {0x44368,0x34b5c}, {0x0,0x0,0x44368,0x34b5c} },
134         { SPOOLSS_FORM_BUILTIN, "A3 Rotated",                     {0x668a0,0x48828}, {0x0,0x0,0x668a0,0x48828} },
135         { SPOOLSS_FORM_BUILTIN, "A4 Rotated",                     {0x48828,0x33450}, {0x0,0x0,0x48828,0x33450} },
136         { SPOOLSS_FORM_BUILTIN, "A5 Rotated",                     {0x33450,0x24220}, {0x0,0x0,0x33450,0x24220} },
137         { SPOOLSS_FORM_BUILTIN, "B4 (JIS) Rotated",               {0x58de0,0x3ebe8}, {0x0,0x0,0x58de0,0x3ebe8} },
138         { SPOOLSS_FORM_BUILTIN, "B5 (JIS) Rotated",               {0x3ebe8,0x2c6f0}, {0x0,0x0,0x3ebe8,0x2c6f0} },
139         { SPOOLSS_FORM_BUILTIN, "Japanese Postcard Rotated",      {0x24220,0x186a0}, {0x0,0x0,0x24220,0x186a0} },
140         { SPOOLSS_FORM_BUILTIN, "Double Japan Postcard Rotated",  {0x24220,0x30d40}, {0x0,0x0,0x24220,0x30d40} },
141         { SPOOLSS_FORM_BUILTIN, "A6 Rotated",                     {0x24220,0x19a28}, {0x0,0x0,0x24220,0x19a28} },
142         { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Kaku #2",      {0x3a980,0x510e0}, {0x0,0x0,0x3a980,0x510e0} },
143         { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Kaku #3",      {0x34bc0,0x43a08}, {0x0,0x0,0x34bc0,0x43a08} },
144         { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Chou #3",      {0x1d4c0,0x395f8}, {0x0,0x0,0x1d4c0,0x395f8} },
145         { SPOOLSS_FORM_BUILTIN, "Japanese Envelope Chou #4",      {0x15f90,0x320c8}, {0x0,0x0,0x15f90,0x320c8} },
146         { SPOOLSS_FORM_BUILTIN, "B6 (JIS)",                       {0x1f400,0x2c6f0}, {0x0,0x0,0x1f400,0x2c6f0} },
147         { SPOOLSS_FORM_BUILTIN, "B6 (JIS) Rotated",               {0x2c6f0,0x1f400}, {0x0,0x0,0x2c6f0,0x1f400} },
148         { SPOOLSS_FORM_BUILTIN, "12x11",                          {0x4a724,0x443e1}, {0x0,0x0,0x4a724,0x443e1} },
149         { SPOOLSS_FORM_BUILTIN, "Japan Envelope You #4",          {0x19a28,0x395f8}, {0x0,0x0,0x19a28,0x395f8} },
150         { SPOOLSS_FORM_BUILTIN, "Japan Envelope You #4 Rotated",  {0x395f8,0x19a28}, {0x0,0x0,0x395f8,0x19a28} },
151         { SPOOLSS_FORM_BUILTIN, "PRC 16K",                        {0x2de60,0x3f7a0}, {0x0,0x0,0x2de60,0x3f7a0} },
152         { SPOOLSS_FORM_BUILTIN, "PRC 32K",                        {0x1fbd0,0x2cec0}, {0x0,0x0,0x1fbd0,0x2cec0} },
153         { SPOOLSS_FORM_BUILTIN, "PRC 32K(Big)",                   {0x222e0,0x318f8}, {0x0,0x0,0x222e0,0x318f8} },
154         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #1",                {0x18e70,0x28488}, {0x0,0x0,0x18e70,0x28488} },
155         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #2",                {0x18e70,0x2af80}, {0x0,0x0,0x18e70,0x2af80} },
156         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #3",                {0x1e848,0x2af80}, {0x0,0x0,0x1e848,0x2af80} },
157         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #4",                {0x1adb0,0x32c80}, {0x0,0x0,0x1adb0,0x32c80} },
158         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #5",                {0x1adb0,0x35b60}, {0x0,0x0,0x1adb0,0x35b60} },
159         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #6",                {0x1d4c0,0x38270}, {0x0,0x0,0x1d4c0,0x38270} },
160         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #7",                {0x27100,0x38270}, {0x0,0x0,0x27100,0x38270} },
161         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #8",                {0x1d4c0,0x4b708}, {0x0,0x0,0x1d4c0,0x4b708} },
162         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #9",                {0x37e88,0x4f1a0}, {0x0,0x0,0x37e88,0x4f1a0} },
163         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #10",               {0x4f1a0,0x6fd10}, {0x0,0x0,0x4f1a0,0x6fd10} },
164         { SPOOLSS_FORM_BUILTIN, "PRC 16K Rotated",                {0x3f7a0,0x2de60}, {0x0,0x0,0x3f7a0,0x2de60} },
165         { SPOOLSS_FORM_BUILTIN, "PRC 32K Rotated",                {0x2cec0,0x1fbd0}, {0x0,0x0,0x2cec0,0x1fbd0} },
166         { SPOOLSS_FORM_BUILTIN, "PRC 32K(Big) Rotated",           {0x318f8,0x222e0}, {0x0,0x0,0x318f8,0x222e0} },
167         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #1 Rotated",        {0x28488,0x18e70}, {0x0,0x0,0x28488,0x18e70} },
168         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #2 Rotated",        {0x2af80,0x18e70}, {0x0,0x0,0x2af80,0x18e70} },
169         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #3 Rotated",        {0x2af80,0x1e848}, {0x0,0x0,0x2af80,0x1e848} },
170         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #4 Rotated",        {0x32c80,0x1adb0}, {0x0,0x0,0x32c80,0x1adb0} },
171         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #5 Rotated",        {0x35b60,0x1adb0}, {0x0,0x0,0x35b60,0x1adb0} },
172         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #6 Rotated",        {0x38270,0x1d4c0}, {0x0,0x0,0x38270,0x1d4c0} },
173         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #7 Rotated",        {0x38270,0x27100}, {0x0,0x0,0x38270,0x27100} },
174         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #8 Rotated",        {0x4b708,0x1d4c0}, {0x0,0x0,0x4b708,0x1d4c0} },
175         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #9 Rotated",        {0x4f1a0,0x37e88}, {0x0,0x0,0x4f1a0,0x37e88} },
176         { SPOOLSS_FORM_BUILTIN, "PRC Envelope #10 Rotated",       {0x6fd10,0x4f1a0}, {0x0,0x0,0x6fd10,0x4f1a0} }
177 };
178
179 /********************************************************************
180  static helper functions
181 ********************************************************************/
182
183 /****************************************************************************
184  Update the changeid time.
185 ****************************************************************************/
186 /**
187  * @internal
188  *
189  * @brief Update the ChangeID time of a printer.
190  *
191  * This is SO NASTY as some drivers need this to change, others need it
192  * static. This value will change every second, and I must hope that this
193  * is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
194  * UTAH ! JRA.
195  *
196  * @return              The ChangeID.
197  */
198 static uint32_t winreg_printer_rev_changeid(void)
199 {
200         struct timeval tv;
201
202         get_process_uptime(&tv);
203
204 #if 1   /* JERRY */
205         /* Return changeid as msec since spooler restart */
206         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
207 #else
208         /*
209          * This setting seems to work well but is too untested
210          * to replace the above calculation.  Left in for experimentation
211          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
212          */
213         return tv.tv_sec * 10 + tv.tv_usec / 100000;
214 #endif
215 }
216
217 static WERROR winreg_printer_openkey(TALLOC_CTX *mem_ctx,
218                               struct dcerpc_binding_handle *binding_handle,
219                               const char *path,
220                               const char *key,
221                               bool create_key,
222                               uint32_t access_mask,
223                               struct policy_handle *hive_handle,
224                               struct policy_handle *key_handle)
225 {
226         struct winreg_String wkey, wkeyclass;
227         char *keyname;
228         NTSTATUS status;
229         WERROR result = WERR_OK;
230
231         status = dcerpc_winreg_OpenHKLM(binding_handle,
232                                         mem_ctx,
233                                         NULL,
234                                         access_mask,
235                                         hive_handle,
236                                         &result);
237         if (!NT_STATUS_IS_OK(status)) {
238                 DEBUG(0, ("winreg_printer_openkey: Could not open HKLM hive: %s\n",
239                           nt_errstr(status)));
240                 return ntstatus_to_werror(status);
241         }
242         if (!W_ERROR_IS_OK(result)) {
243                 DEBUG(0, ("winreg_printer_openkey: Could not open HKLM hive: %s\n",
244                           win_errstr(result)));
245                 return result;
246         }
247
248         if (key && *key) {
249                 keyname = talloc_asprintf(mem_ctx, "%s\\%s", path, key);
250         } else {
251                 keyname = talloc_strdup(mem_ctx, path);
252         }
253         if (keyname == NULL) {
254                 return WERR_NOMEM;
255         }
256
257         ZERO_STRUCT(wkey);
258         wkey.name = keyname;
259
260         if (create_key) {
261                 enum winreg_CreateAction action = REG_ACTION_NONE;
262
263                 ZERO_STRUCT(wkeyclass);
264                 wkeyclass.name = "";
265
266                 status = dcerpc_winreg_CreateKey(binding_handle,
267                                                  mem_ctx,
268                                                  hive_handle,
269                                                  wkey,
270                                                  wkeyclass,
271                                                  0,
272                                                  access_mask,
273                                                  NULL,
274                                                  key_handle,
275                                                  &action,
276                                                  &result);
277                 switch (action) {
278                         case REG_ACTION_NONE:
279                                 DEBUG(8, ("winreg_printer_openkey:createkey did nothing -- huh?\n"));
280                                 break;
281                         case REG_CREATED_NEW_KEY:
282                                 DEBUG(8, ("winreg_printer_openkey: createkey created %s\n", keyname));
283                                 break;
284                         case REG_OPENED_EXISTING_KEY:
285                                 DEBUG(8, ("winreg_printer_openkey: createkey opened existing %s\n", keyname));
286                                 break;
287                 }
288         } else {
289                 status = dcerpc_winreg_OpenKey(binding_handle,
290                                                mem_ctx,
291                                                hive_handle,
292                                                wkey,
293                                                0,
294                                                access_mask,
295                                                key_handle,
296                                                &result);
297         }
298         if (!NT_STATUS_IS_OK(status)) {
299                 result = ntstatus_to_werror(status);
300         }
301         if (!W_ERROR_IS_OK(result)) {
302                 WERROR ignore;
303
304                 if (is_valid_policy_hnd(hive_handle)) {
305                         dcerpc_winreg_CloseKey(binding_handle,
306                                                mem_ctx,
307                                                hive_handle,
308                                                &ignore);
309                 }
310                 ZERO_STRUCTP(hive_handle);
311
312                 return result;
313         }
314
315         return WERR_OK;
316 }
317
318 /**
319  * @brief Create the registry keyname for the given printer.
320  *
321  * @param[in]  mem_ctx  The memory context to use.
322  *
323  * @param[in]  printer  The name of the printer to get the registry key.
324  *
325  * @return     The registry key or NULL on error.
326  */
327 static char *winreg_printer_data_keyname(TALLOC_CTX *mem_ctx, const char *printer) {
328         return talloc_asprintf(mem_ctx, "%s\\%s", TOP_LEVEL_PRINT_PRINTERS_KEY, printer);
329 }
330
331 static WERROR winreg_printer_opendriver(TALLOC_CTX *mem_ctx,
332                                         struct dcerpc_binding_handle *winreg_handle,
333                                         const char *drivername,
334                                         const char *architecture,
335                                         uint32_t version,
336                                         uint32_t access_mask,
337                                         bool create,
338                                         struct policy_handle *hive_hnd,
339                                         struct policy_handle *key_hnd)
340 {
341         WERROR result;
342         char *key_name;
343
344         key_name = talloc_asprintf(mem_ctx, "%s\\Environments\\%s\\Drivers\\Version-%u",
345                                    TOP_LEVEL_CONTROL_KEY,
346                                    architecture, version);
347         if (!key_name) {
348                 return WERR_NOMEM;
349         }
350
351         result = winreg_printer_openkey(mem_ctx,
352                                         winreg_handle,
353                                         key_name,
354                                         drivername,
355                                         create,
356                                         access_mask,
357                                         hive_hnd,
358                                         key_hnd);
359         return result;
360 }
361
362 static WERROR winreg_enumval_to_dword(TALLOC_CTX *mem_ctx,
363                                       struct spoolss_PrinterEnumValues *v,
364                                       const char *valuename, uint32_t *dw)
365 {
366         /* just return if it is not the one we are looking for */
367         if (strcmp(valuename, v->value_name) != 0) {
368                 return WERR_NOT_FOUND;
369         }
370
371         if (v->type != REG_DWORD) {
372                 return WERR_INVALID_DATATYPE;
373         }
374
375         if (v->data_length != 4) {
376                 *dw = 0;
377                 return WERR_OK;
378         }
379
380         *dw = IVAL(v->data->data, 0);
381         return WERR_OK;
382 }
383
384 static WERROR winreg_enumval_to_sz(TALLOC_CTX *mem_ctx,
385                                    struct spoolss_PrinterEnumValues *v,
386                                    const char *valuename, const char **_str)
387 {
388         /* just return if it is not the one we are looking for */
389         if (strcmp(valuename, v->value_name) != 0) {
390                 return WERR_NOT_FOUND;
391         }
392
393         if (v->type != REG_SZ) {
394                 return WERR_INVALID_DATATYPE;
395         }
396
397         if (v->data_length == 0) {
398                 *_str = talloc_strdup(mem_ctx, EMPTY_STRING);
399                 if (*_str == NULL) {
400                         return WERR_NOMEM;
401                 }
402                 return WERR_OK;
403         }
404
405         if (!pull_reg_sz(mem_ctx, v->data, _str)) {
406                 return WERR_NOMEM;
407         }
408
409         return WERR_OK;
410 }
411
412 static WERROR winreg_enumval_to_multi_sz(TALLOC_CTX *mem_ctx,
413                                          struct spoolss_PrinterEnumValues *v,
414                                          const char *valuename,
415                                          const char ***array)
416 {
417         /* just return if it is not the one we are looking for */
418         if (strcmp(valuename, v->value_name) != 0) {
419                 return WERR_NOT_FOUND;
420         }
421
422         if (v->type != REG_MULTI_SZ) {
423                 return WERR_INVALID_DATATYPE;
424         }
425
426         if (v->data_length == 0) {
427                 *array = talloc_array(mem_ctx, const char *, 1);
428                 if (*array == NULL) {
429                         return WERR_NOMEM;
430                 }
431                 *array[0] = NULL;
432                 return WERR_OK;
433         }
434
435         if (!pull_reg_multi_sz(mem_ctx, v->data, array)) {
436                 return WERR_NOMEM;
437         }
438
439         return WERR_OK;
440 }
441
442 static WERROR winreg_printer_write_date(TALLOC_CTX *mem_ctx,
443                                         struct dcerpc_binding_handle *winreg_handle,
444                                         struct policy_handle *key_handle,
445                                         const char *value,
446                                         NTTIME data)
447 {
448         struct winreg_String wvalue = { 0, };
449         DATA_BLOB blob;
450         WERROR result = WERR_OK;
451         NTSTATUS status;
452         const char *str;
453         struct tm *tm;
454         time_t t;
455
456         if (data == 0) {
457                 str = talloc_strdup(mem_ctx, "01/01/1601");
458         } else {
459                 t = nt_time_to_unix(data);
460                 tm = localtime(&t);
461                 if (tm == NULL) {
462                         return map_werror_from_unix(errno);
463                 }
464                 str = talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
465                                       tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
466         }
467         if (!str) {
468                 return WERR_NOMEM;
469         }
470
471         wvalue.name = value;
472         if (!push_reg_sz(mem_ctx, &blob, str)) {
473                 return WERR_NOMEM;
474         }
475         status = dcerpc_winreg_SetValue(winreg_handle,
476                                         mem_ctx,
477                                         key_handle,
478                                         wvalue,
479                                         REG_SZ,
480                                         blob.data,
481                                         blob.length,
482                                         &result);
483         if (!NT_STATUS_IS_OK(status)) {
484                 result = ntstatus_to_werror(status);
485         }
486         if (!W_ERROR_IS_OK(result)) {
487                 DEBUG(0, ("winreg_printer_write_date: Could not set value %s: %s\n",
488                         wvalue.name, win_errstr(result)));
489         }
490
491         return result;
492 }
493
494 static WERROR winreg_printer_date_to_NTTIME(const char *str, NTTIME *data)
495 {
496         struct tm tm;
497         time_t t;
498
499         if (strequal(str, "01/01/1601")) {
500                 *data = 0;
501                 return WERR_OK;
502         }
503
504         ZERO_STRUCT(tm);
505
506         if (sscanf(str, "%d/%d/%d",
507                    &tm.tm_mon, &tm.tm_mday, &tm.tm_year) != 3) {
508                 return WERR_INVALID_PARAMETER;
509         }
510         tm.tm_mon -= 1;
511         tm.tm_year -= 1900;
512         tm.tm_isdst = -1;
513
514         t = mktime(&tm);
515         unix_to_nt_time(data, t);
516
517         return WERR_OK;
518 }
519
520 static WERROR winreg_printer_write_ver(TALLOC_CTX *mem_ctx,
521                                        struct dcerpc_binding_handle *winreg_handle,
522                                        struct policy_handle *key_handle,
523                                        const char *value,
524                                        uint64_t data)
525 {
526         struct winreg_String wvalue = { 0, };
527         DATA_BLOB blob;
528         WERROR result = WERR_OK;
529         NTSTATUS status;
530         char *str;
531
532         /* FIXME: check format is right,
533          *      this needs to be something like: 6.1.7600.16385 */
534         str = talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
535                               (unsigned)((data >> 48) & 0xFFFF),
536                               (unsigned)((data >> 32) & 0xFFFF),
537                               (unsigned)((data >> 16) & 0xFFFF),
538                               (unsigned)(data & 0xFFFF));
539         if (!str) {
540                 return WERR_NOMEM;
541         }
542
543         wvalue.name = value;
544         if (!push_reg_sz(mem_ctx, &blob, str)) {
545                 return WERR_NOMEM;
546         }
547         status = dcerpc_winreg_SetValue(winreg_handle,
548                                         mem_ctx,
549                                         key_handle,
550                                         wvalue,
551                                         REG_SZ,
552                                         blob.data,
553                                         blob.length,
554                                         &result);
555         if (!NT_STATUS_IS_OK(status)) {
556                 result = ntstatus_to_werror(status);
557         }
558         if (!W_ERROR_IS_OK(result)) {
559                 DEBUG(0, ("winreg_printer_write_date: Could not set value %s: %s\n",
560                         wvalue.name, win_errstr(result)));
561         }
562
563         return result;
564 }
565
566 static WERROR winreg_printer_ver_to_dword(const char *str, uint64_t *data)
567 {
568         unsigned int v1, v2, v3, v4;
569
570         if (sscanf(str, "%u.%u.%u.%u", &v1, &v2, &v3, &v4) != 4) {
571                 return WERR_INVALID_PARAMETER;
572         }
573
574         *data = ((uint64_t)(v1 & 0xFFFF) << 48) +
575                 ((uint64_t)(v2 & 0xFFFF) << 32) +
576                 ((uint64_t)(v3 & 0xFFFF) << 16) +
577                 (uint64_t)(v2 & 0xFFFF);
578
579         return WERR_OK;
580 }
581
582 /********************************************************************
583  Public winreg function for spoolss
584 ********************************************************************/
585
586 WERROR winreg_create_printer(TALLOC_CTX *mem_ctx,
587                              struct dcerpc_binding_handle *winreg_handle,
588                              const char *sharename)
589 {
590         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
591         struct policy_handle hive_hnd, key_hnd;
592         struct spoolss_SetPrinterInfo2 *info2;
593         struct security_descriptor *secdesc;
594         struct winreg_String wkey, wkeyclass;
595         const char *path;
596         const char *subkeys[] = { SPOOL_DSDRIVER_KEY, SPOOL_DSSPOOLER_KEY, SPOOL_PRINTERDATA_KEY };
597         uint32_t i, count = ARRAY_SIZE(subkeys);
598         uint32_t info2_mask = 0;
599         WERROR result = WERR_OK;
600         WERROR ignore;
601         TALLOC_CTX *tmp_ctx;
602
603         tmp_ctx = talloc_stackframe();
604         if (tmp_ctx == NULL) {
605                 return WERR_NOMEM;
606         }
607
608         path = winreg_printer_data_keyname(tmp_ctx, sharename);
609         if (path == NULL) {
610                 TALLOC_FREE(tmp_ctx);
611                 return WERR_NOMEM;
612         }
613
614         ZERO_STRUCT(hive_hnd);
615         ZERO_STRUCT(key_hnd);
616
617         result = winreg_printer_openkey(tmp_ctx,
618                                         winreg_handle,
619                                         path,
620                                         "",
621                                         false,
622                                         access_mask,
623                                         &hive_hnd,
624                                         &key_hnd);
625         if (W_ERROR_IS_OK(result)) {
626                 DEBUG(2, ("winreg_create_printer: Skipping, %s already exists\n", path));
627                 goto done;
628         } else if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
629                 DEBUG(2, ("winreg_create_printer: Creating default values in %s\n", path));
630         } else if (!W_ERROR_IS_OK(result)) {
631                 DEBUG(0, ("winreg_create_printer: Could not open key %s: %s\n",
632                         path, win_errstr(result)));
633                 goto done;
634         }
635
636         if (is_valid_policy_hnd(&key_hnd)) {
637                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
638         }
639         if (is_valid_policy_hnd(&hive_hnd)) {
640                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
641         }
642
643         /* Create the main key */
644         result = winreg_printer_openkey(tmp_ctx,
645                                         winreg_handle,
646                                         path,
647                                         "",
648                                         true,
649                                         access_mask,
650                                         &hive_hnd,
651                                         &key_hnd);
652         if (!W_ERROR_IS_OK(result)) {
653                 DEBUG(0, ("winreg_create_printer_keys: Could not create key %s: %s\n",
654                         path, win_errstr(result)));
655                 goto done;
656         }
657
658         if (is_valid_policy_hnd(&key_hnd)) {
659                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &result);
660         }
661
662         /* Create subkeys */
663         for (i = 0; i < count; i++) {
664                 NTSTATUS status;
665                 enum winreg_CreateAction action = REG_ACTION_NONE;
666
667                 ZERO_STRUCT(key_hnd);
668                 ZERO_STRUCT(wkey);
669
670                 wkey.name = talloc_asprintf(tmp_ctx, "%s\\%s", path, subkeys[i]);
671                 if (wkey.name == NULL) {
672                         result = WERR_NOMEM;
673                         goto done;
674                 }
675
676                 ZERO_STRUCT(wkeyclass);
677                 wkeyclass.name = "";
678
679                 status = dcerpc_winreg_CreateKey(winreg_handle,
680                                                  tmp_ctx,
681                                                  &hive_hnd,
682                                                  wkey,
683                                                  wkeyclass,
684                                                  0,
685                                                  access_mask,
686                                                  NULL,
687                                                  &key_hnd,
688                                                  &action,
689                                                  &result);
690                 if (!NT_STATUS_IS_OK(status)) {
691                         result = ntstatus_to_werror(status);
692                 }
693                 if (!W_ERROR_IS_OK(result)) {
694                         DEBUG(0, ("winreg_create_printer_keys: Could not create key %s: %s\n",
695                                 wkey.name, win_errstr(result)));
696                         goto done;
697                 }
698
699                 if (strequal(subkeys[i], SPOOL_DSSPOOLER_KEY)) {
700                         const char *dnssuffix;
701                         const char *longname;
702                         const char *uncname;
703
704                         status = dcerpc_winreg_set_sz(tmp_ctx,
705                                                       winreg_handle,
706                                                       &key_hnd,
707                                                       SPOOL_REG_PRINTERNAME,
708                                                       sharename,
709                                                       &result);
710                         if (!NT_STATUS_IS_OK(status)) {
711                                 result = ntstatus_to_werror(status);
712                         }
713                         if (!W_ERROR_IS_OK(result)) {
714                                 goto done;
715                         }
716
717                         status = dcerpc_winreg_set_sz(tmp_ctx,
718                                                       winreg_handle,
719                                                       &key_hnd,
720                                                       SPOOL_REG_SHORTSERVERNAME,
721                                                       lp_netbios_name(),
722                                                       &result);
723                         if (!NT_STATUS_IS_OK(status)) {
724                                 result = ntstatus_to_werror(status);
725                         }
726                         if (!W_ERROR_IS_OK(result)) {
727                                 goto done;
728                         }
729
730                         /* We make the assumption that the netbios name
731                          * is the same as the DNS name since the former
732                          * will be what we used to join the domain
733                          */
734                         dnssuffix = get_mydnsdomname(tmp_ctx);
735                         if (dnssuffix != NULL && dnssuffix[0] != '\0') {
736                                 longname = talloc_asprintf(tmp_ctx, "%s.%s", lp_netbios_name(), dnssuffix);
737                         } else {
738                                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
739                         }
740                         if (longname == NULL) {
741                                 result = WERR_NOMEM;
742                                 goto done;
743                         }
744
745                         status = dcerpc_winreg_set_sz(tmp_ctx,
746                                                       winreg_handle,
747                                                       &key_hnd,
748                                                       SPOOL_REG_SERVERNAME,
749                                                       longname,
750                                                       &result);
751                         if (!NT_STATUS_IS_OK(status)) {
752                                 result = ntstatus_to_werror(status);
753                         }
754                         if (!W_ERROR_IS_OK(result)) {
755                                 goto done;
756                         }
757
758                         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
759                                                   longname, sharename);
760                         if (uncname == NULL) {
761                                 result = WERR_NOMEM;
762                                 goto done;
763                         }
764
765                         status = dcerpc_winreg_set_sz(tmp_ctx,
766                                                       winreg_handle,
767                                                       &key_hnd,
768                                                       SPOOL_REG_UNCNAME,
769                                                       uncname,
770                                                       &result);
771                         if (!NT_STATUS_IS_OK(status)) {
772                                 result = ntstatus_to_werror(status);
773                         }
774                         if (!W_ERROR_IS_OK(result)) {
775                                 goto done;
776                         }
777
778                         status = dcerpc_winreg_set_dword(tmp_ctx,
779                                                          winreg_handle,
780                                                          &key_hnd,
781                                                          SPOOL_REG_VERSIONNUMBER,
782                                                          4,
783                                                          &result);
784                         if (!NT_STATUS_IS_OK(status)) {
785                                 result = ntstatus_to_werror(status);
786                         }
787                         if (!W_ERROR_IS_OK(result)) {
788                                 goto done;
789                         }
790
791                         status = dcerpc_winreg_set_dword(tmp_ctx,
792                                                          winreg_handle,
793                                                          &key_hnd,
794                                                          SPOOL_REG_PRINTSTARTTIME,
795                                                          0,
796                                                          &result);
797                         if (!NT_STATUS_IS_OK(status)) {
798                                 result = ntstatus_to_werror(status);
799                         }
800                         if (!W_ERROR_IS_OK(result)) {
801                                 goto done;
802                         }
803
804                         status = dcerpc_winreg_set_dword(tmp_ctx,
805                                                          winreg_handle,
806                                                          &key_hnd,
807                                                          SPOOL_REG_PRINTENDTIME,
808                                                          0,
809                                                          &result);
810                         if (!NT_STATUS_IS_OK(status)) {
811                                 result = ntstatus_to_werror(status);
812                         }
813                         if (!W_ERROR_IS_OK(result)) {
814                                 goto done;
815                         }
816
817                         status = dcerpc_winreg_set_dword(tmp_ctx,
818                                                          winreg_handle,
819                                                          &key_hnd,
820                                                          SPOOL_REG_PRIORITY,
821                                                          1,
822                                                          &result);
823                         if (!NT_STATUS_IS_OK(status)) {
824                                 result = ntstatus_to_werror(status);
825                         }
826                         if (!W_ERROR_IS_OK(result)) {
827                                 goto done;
828                         }
829
830                         status = dcerpc_winreg_set_dword(tmp_ctx,
831                                                          winreg_handle,
832                                                          &key_hnd,
833                                                          SPOOL_REG_PRINTKEEPPRINTEDJOBS,
834                                                          0,
835                                                          &result);
836                         if (!NT_STATUS_IS_OK(status)) {
837                                 result = ntstatus_to_werror(status);
838                         }
839                         if (!W_ERROR_IS_OK(result)) {
840                                 goto done;
841                         }
842                 }
843
844                 if (is_valid_policy_hnd(&key_hnd)) {
845                         dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &result);
846                 }
847         }
848         info2 = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
849         if (info2 == NULL) {
850                 result = WERR_NOMEM;
851                 goto done;
852         }
853
854         info2->printername = sharename;
855         if (info2->printername == NULL) {
856                 result = WERR_NOMEM;
857                 goto done;
858         }
859         info2_mask |= SPOOLSS_PRINTER_INFO_PRINTERNAME;
860
861         info2->sharename = sharename;
862         info2_mask |= SPOOLSS_PRINTER_INFO_SHARENAME;
863
864         info2->portname = SAMBA_PRINTER_PORT_NAME;
865         info2_mask |= SPOOLSS_PRINTER_INFO_PORTNAME;
866
867         info2->printprocessor = "winprint";
868         info2_mask |= SPOOLSS_PRINTER_INFO_PRINTPROCESSOR;
869
870         info2->datatype = "RAW";
871         info2_mask |= SPOOLSS_PRINTER_INFO_DATATYPE;
872
873         info2->comment = "";
874         info2_mask |= SPOOLSS_PRINTER_INFO_COMMENT;
875
876         info2->attributes = PRINTER_ATTRIBUTE_SAMBA;
877         info2_mask |= SPOOLSS_PRINTER_INFO_ATTRIBUTES;
878
879         info2->starttime = 0; /* Minutes since 12:00am GMT */
880         info2_mask |= SPOOLSS_PRINTER_INFO_STARTTIME;
881
882         info2->untiltime = 0; /* Minutes since 12:00am GMT */
883         info2_mask |= SPOOLSS_PRINTER_INFO_UNTILTIME;
884
885         info2->priority = 1;
886         info2_mask |= SPOOLSS_PRINTER_INFO_PRIORITY;
887
888         info2->defaultpriority = 1;
889         info2_mask |= SPOOLSS_PRINTER_INFO_DEFAULTPRIORITY;
890
891         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
892         if (!W_ERROR_IS_OK(result)) {
893                 goto done;
894         }
895         info2_mask |= SPOOLSS_PRINTER_INFO_SECDESC;
896
897         /*
898          * Don't write a default Device Mode to the registry! The Device Mode is
899          * only written to disk with a SetPrinter level 2 or 8.
900          */
901
902         result = winreg_update_printer(tmp_ctx,
903                                        winreg_handle,
904                                        sharename,
905                                        info2_mask,
906                                        info2,
907                                        NULL,
908                                        secdesc);
909
910 done:
911         if (is_valid_policy_hnd(&key_hnd)) {
912                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
913         }
914         if (is_valid_policy_hnd(&hive_hnd)) {
915                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
916         }
917
918         talloc_free(tmp_ctx);
919         return result;
920 }
921
922 WERROR winreg_update_printer(TALLOC_CTX *mem_ctx,
923                              struct dcerpc_binding_handle *winreg_handle,
924                              const char *sharename,
925                              uint32_t info2_mask,
926                              struct spoolss_SetPrinterInfo2 *info2,
927                              struct spoolss_DeviceMode *devmode,
928                              struct security_descriptor *secdesc)
929 {
930         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
931         struct policy_handle hive_hnd, key_hnd;
932         int snum = lp_servicenumber(sharename);
933         enum ndr_err_code ndr_err;
934         DATA_BLOB blob;
935         char *path;
936         WERROR result = WERR_OK;
937         WERROR ignore;
938         NTSTATUS status;
939         TALLOC_CTX *tmp_ctx;
940
941         tmp_ctx = talloc_stackframe();
942         if (tmp_ctx == NULL) {
943                 return WERR_NOMEM;
944         }
945
946         path = winreg_printer_data_keyname(tmp_ctx, sharename);
947         if (path == NULL) {
948                 TALLOC_FREE(tmp_ctx);
949                 return WERR_NOMEM;
950         }
951
952         ZERO_STRUCT(hive_hnd);
953         ZERO_STRUCT(key_hnd);
954
955         result = winreg_printer_openkey(tmp_ctx,
956                                         winreg_handle,
957                                         path,
958                                         "",
959                                         true,
960                                         access_mask,
961                                         &hive_hnd,
962                                         &key_hnd);
963         if (!W_ERROR_IS_OK(result)) {
964                 DEBUG(0, ("winreg_update_printer: Could not open key %s: %s\n",
965                         path, win_errstr(result)));
966                 goto done;
967         }
968
969         if (info2_mask & SPOOLSS_PRINTER_INFO_ATTRIBUTES) {
970                 status = dcerpc_winreg_set_dword(tmp_ctx,
971                                                  winreg_handle,
972                                                  &key_hnd,
973                                                  "Attributes",
974                                                  info2->attributes,
975                                                  &result);
976                 if (!NT_STATUS_IS_OK(status)) {
977                         result = ntstatus_to_werror(status);
978                 }
979                 if (!W_ERROR_IS_OK(result)) {
980                         goto done;
981                 }
982         }
983
984 #if 0
985         if (info2_mask & SPOOLSS_PRINTER_INFO_AVERAGEPPM) {
986                 status = dcerpc_winreg_set_dword(tmp_ctx,
987                                                  winreg_handle,
988                                                  &key_hnd,
989                                                  "AveragePpm",
990                                                  info2->attributes,
991                                                  &result);
992                 if (!NT_STATUS_IS_OK(status)) {
993                         result = ntstatus_to_werror(status);
994                 }
995                 if (!W_ERROR_IS_OK(result)) {
996                         goto done;
997                 }
998         }
999 #endif
1000
1001         if (info2_mask & SPOOLSS_PRINTER_INFO_COMMENT) {
1002                 status = dcerpc_winreg_set_sz(tmp_ctx,
1003                                               winreg_handle,
1004                                               &key_hnd,
1005                                               "Description",
1006                                               info2->comment,
1007                                               &result);
1008                 if (!NT_STATUS_IS_OK(status)) {
1009                         result = ntstatus_to_werror(status);
1010                 }
1011                 if (!W_ERROR_IS_OK(result)) {
1012                         goto done;
1013                 }
1014         }
1015
1016         if (info2_mask & SPOOLSS_PRINTER_INFO_DATATYPE) {
1017                 status = dcerpc_winreg_set_sz(tmp_ctx,
1018                                               winreg_handle,
1019                                               &key_hnd,
1020                                               "Datatype",
1021                                               info2->datatype,
1022                                               &result);
1023                 if (!NT_STATUS_IS_OK(status)) {
1024                         result = ntstatus_to_werror(status);
1025                 }
1026                 if (!W_ERROR_IS_OK(result)) {
1027                         goto done;
1028                 }
1029         }
1030
1031         if (info2_mask & SPOOLSS_PRINTER_INFO_DEFAULTPRIORITY) {
1032                 status = dcerpc_winreg_set_dword(tmp_ctx,
1033                                                  winreg_handle,
1034                                                  &key_hnd,
1035                                                  "Default Priority",
1036                                                  info2->defaultpriority,
1037                                                  &result);
1038                 if (!NT_STATUS_IS_OK(status)) {
1039                         result = ntstatus_to_werror(status);
1040                 }
1041                 if (!W_ERROR_IS_OK(result)) {
1042                         goto done;
1043                 }
1044         }
1045
1046         if (info2_mask & SPOOLSS_PRINTER_INFO_DEVMODE) {
1047                 /*
1048                  * Some client drivers freak out if there is a NULL devmode
1049                  * (probably the driver is not checking before accessing
1050                  * the devmode pointer)   --jerry
1051                  */
1052                 if (devmode == NULL && lp_default_devmode(snum) && info2 != NULL) {
1053                         result = spoolss_create_default_devmode(tmp_ctx,
1054                                                                 info2->printername,
1055                                                                 &devmode);
1056                         if (!W_ERROR_IS_OK(result)) {
1057                                 goto done;
1058                         }
1059                 }
1060
1061                 if (devmode->size != (ndr_size_spoolss_DeviceMode(devmode, 0) - devmode->__driverextra_length)) {
1062                         result = WERR_INVALID_PARAM;
1063                         goto done;
1064                 }
1065
1066                 ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, devmode,
1067                                 (ndr_push_flags_fn_t) ndr_push_spoolss_DeviceMode);
1068                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1069                         DEBUG(0, ("winreg_update_printer: Failed to marshall device mode\n"));
1070                         result = WERR_NOMEM;
1071                         goto done;
1072                 }
1073
1074                 status = dcerpc_winreg_set_binary(tmp_ctx,
1075                                                   winreg_handle,
1076                                                   &key_hnd,
1077                                                   "Default DevMode",
1078                                                   &blob,
1079                                                   &result);
1080                 if (!NT_STATUS_IS_OK(status)) {
1081                         result = ntstatus_to_werror(status);
1082                 }
1083                 if (!W_ERROR_IS_OK(result)) {
1084                         goto done;
1085                 }
1086         }
1087
1088         if (info2_mask & SPOOLSS_PRINTER_INFO_DRIVERNAME) {
1089                 status = dcerpc_winreg_set_sz(tmp_ctx,
1090                                               winreg_handle,
1091                                               &key_hnd,
1092                                               "Printer Driver",
1093                                               info2->drivername,
1094                                               &result);
1095                 if (!NT_STATUS_IS_OK(status)) {
1096                         result = ntstatus_to_werror(status);
1097                 }
1098                 if (!W_ERROR_IS_OK(result)) {
1099                         goto done;
1100                 }
1101         }
1102
1103         if (info2_mask & SPOOLSS_PRINTER_INFO_LOCATION) {
1104                 status = dcerpc_winreg_set_sz(tmp_ctx,
1105                                               winreg_handle,
1106                                               &key_hnd,
1107                                               "Location",
1108                                               info2->location,
1109                                               &result);
1110                 if (!NT_STATUS_IS_OK(status)) {
1111                         result = ntstatus_to_werror(status);
1112                 }
1113                 if (!W_ERROR_IS_OK(result)) {
1114                         goto done;
1115                 }
1116         }
1117
1118         if (info2_mask & SPOOLSS_PRINTER_INFO_PARAMETERS) {
1119                 status = dcerpc_winreg_set_sz(tmp_ctx,
1120                                               winreg_handle,
1121                                               &key_hnd,
1122                                               "Parameters",
1123                                               info2->parameters,
1124                                               &result);
1125                 if (!NT_STATUS_IS_OK(status)) {
1126                         result = ntstatus_to_werror(status);
1127                 }
1128                 if (!W_ERROR_IS_OK(result)) {
1129                         goto done;
1130                 }
1131         }
1132
1133         if (info2_mask & SPOOLSS_PRINTER_INFO_PORTNAME) {
1134                 status = dcerpc_winreg_set_sz(tmp_ctx,
1135                                               winreg_handle,
1136                                               &key_hnd,
1137                                               "Port",
1138                                               info2->portname,
1139                                               &result);
1140                 if (!NT_STATUS_IS_OK(status)) {
1141                         result = ntstatus_to_werror(status);
1142                 }
1143                 if (!W_ERROR_IS_OK(result)) {
1144                         goto done;
1145                 }
1146         }
1147
1148         if (info2_mask & SPOOLSS_PRINTER_INFO_PRINTERNAME) {
1149                 /*
1150                  * in addprinter: no servername and the printer is the name
1151                  * in setprinter: servername is \\server
1152                  *                and printer is \\server\\printer
1153                  *
1154                  * Samba manages only local printers.
1155                  * we currently don't support things like i
1156                  * path=\\other_server\printer
1157                  *
1158                  * We only store the printername, not \\server\printername
1159                  */
1160                 const char *p = strrchr(info2->printername, '\\');
1161                 if (p == NULL) {
1162                         p = info2->printername;
1163                 } else {
1164                         p++;
1165                 }
1166                 status = dcerpc_winreg_set_sz(tmp_ctx,
1167                                               winreg_handle,
1168                                               &key_hnd,
1169                                               "Name",
1170                                               p,
1171                                               &result);
1172                 if (!NT_STATUS_IS_OK(status)) {
1173                         result = ntstatus_to_werror(status);
1174                 }
1175                 if (!W_ERROR_IS_OK(result)) {
1176                         goto done;
1177                 }
1178         }
1179
1180         if (info2_mask & SPOOLSS_PRINTER_INFO_PRINTPROCESSOR) {
1181                 status = dcerpc_winreg_set_sz(tmp_ctx,
1182                                               winreg_handle,
1183                                               &key_hnd,
1184                                               "Print Processor",
1185                                               info2->printprocessor,
1186                                               &result);
1187                 if (!NT_STATUS_IS_OK(status)) {
1188                         result = ntstatus_to_werror(status);
1189                 }
1190                 if (!W_ERROR_IS_OK(result)) {
1191                         goto done;
1192                 }
1193         }
1194
1195         if (info2_mask & SPOOLSS_PRINTER_INFO_PRIORITY) {
1196                 status = dcerpc_winreg_set_dword(tmp_ctx,
1197                                                  winreg_handle,
1198                                                  &key_hnd,
1199                                                  "Priority",
1200                                                  info2->priority,
1201                                                  &result);
1202                 if (!NT_STATUS_IS_OK(status)) {
1203                         result = ntstatus_to_werror(status);
1204                 }
1205                 if (!W_ERROR_IS_OK(result)) {
1206                         goto done;
1207                 }
1208         }
1209
1210         if (info2_mask & SPOOLSS_PRINTER_INFO_SECDESC) {
1211                 /*
1212                  * We need a security descriptor, if it isn't specified by
1213                  * AddPrinter{Ex} then create a default descriptor.
1214                  */
1215                 if (secdesc == NULL) {
1216                         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
1217                         if (!W_ERROR_IS_OK(result)) {
1218                                 goto done;
1219                         }
1220                 }
1221                 result = winreg_set_printer_secdesc(tmp_ctx,
1222                                                     winreg_handle,
1223                                                     sharename,
1224                                                     secdesc);
1225                 if (!W_ERROR_IS_OK(result)) {
1226                         goto done;
1227                 }
1228         }
1229
1230         if (info2_mask & SPOOLSS_PRINTER_INFO_SEPFILE) {
1231                 status = dcerpc_winreg_set_sz(tmp_ctx,
1232                                               winreg_handle,
1233                                               &key_hnd,
1234                                               "Separator File",
1235                                               info2->sepfile,
1236                                               &result);
1237                 if (!NT_STATUS_IS_OK(status)) {
1238                         result = ntstatus_to_werror(status);
1239                 }
1240                 if (!W_ERROR_IS_OK(result)) {
1241                         goto done;
1242                 }
1243         }
1244
1245         if (info2_mask & SPOOLSS_PRINTER_INFO_SHARENAME) {
1246                 status = dcerpc_winreg_set_sz(tmp_ctx,
1247                                               winreg_handle,
1248                                               &key_hnd,
1249                                               "Share Name",
1250                                               info2->sharename,
1251                                               &result);
1252                 if (!NT_STATUS_IS_OK(status)) {
1253                         result = ntstatus_to_werror(status);
1254                 }
1255                 if (!W_ERROR_IS_OK(result)) {
1256                         goto done;
1257                 }
1258         }
1259
1260         if (info2_mask & SPOOLSS_PRINTER_INFO_STARTTIME) {
1261                 status = dcerpc_winreg_set_dword(tmp_ctx,
1262                                                  winreg_handle,
1263                                                  &key_hnd,
1264                                                  "StartTime",
1265                                                  info2->starttime,
1266                                                  &result);
1267                 if (!NT_STATUS_IS_OK(status)) {
1268                         result = ntstatus_to_werror(status);
1269                 }
1270                 if (!W_ERROR_IS_OK(result)) {
1271                         goto done;
1272                 }
1273         }
1274
1275         if (info2_mask & SPOOLSS_PRINTER_INFO_STATUS) {
1276                 status = dcerpc_winreg_set_dword(tmp_ctx,
1277                                                  winreg_handle,
1278                                                  &key_hnd,
1279                                                  "Status",
1280                                                  info2->status,
1281                                                  &result);
1282                 if (!NT_STATUS_IS_OK(status)) {
1283                         result = ntstatus_to_werror(status);
1284                 }
1285                 if (!W_ERROR_IS_OK(result)) {
1286                         goto done;
1287                 }
1288         }
1289
1290         if (info2_mask & SPOOLSS_PRINTER_INFO_UNTILTIME) {
1291                 status = dcerpc_winreg_set_dword(tmp_ctx,
1292                                                  winreg_handle,
1293                                                  &key_hnd,
1294                                                  "UntilTime",
1295                                                  info2->untiltime,
1296                                                  &result);
1297                 if (!NT_STATUS_IS_OK(status)) {
1298                         result = ntstatus_to_werror(status);
1299                 }
1300                 if (!W_ERROR_IS_OK(result)) {
1301                         goto done;
1302                 }
1303         }
1304
1305         status = dcerpc_winreg_set_dword(tmp_ctx,
1306                                          winreg_handle,
1307                                          &key_hnd,
1308                                          "ChangeID",
1309                                          winreg_printer_rev_changeid(),
1310                                          &result);
1311         if (!NT_STATUS_IS_OK(status)) {
1312                 result = ntstatus_to_werror(status);
1313         }
1314         if (!W_ERROR_IS_OK(result)) {
1315                 goto done;
1316         }
1317
1318         result = WERR_OK;
1319 done:
1320         if (is_valid_policy_hnd(&key_hnd)) {
1321                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1322         }
1323         if (is_valid_policy_hnd(&hive_hnd)) {
1324                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1325         }
1326
1327         TALLOC_FREE(tmp_ctx);
1328         return result;
1329 }
1330
1331 WERROR winreg_get_printer(TALLOC_CTX *mem_ctx,
1332                           struct dcerpc_binding_handle *winreg_handle,
1333                           const char *printer,
1334                           struct spoolss_PrinterInfo2 **pinfo2)
1335 {
1336         struct spoolss_PrinterInfo2 *info2;
1337         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1338         struct policy_handle hive_hnd, key_hnd;
1339         struct spoolss_PrinterEnumValues enum_value;
1340         struct spoolss_PrinterEnumValues *v = NULL;
1341         enum ndr_err_code ndr_err;
1342         DATA_BLOB blob;
1343         int snum = lp_servicenumber(printer);
1344         uint32_t num_values = 0;
1345         uint32_t i;
1346         char *path;
1347         NTSTATUS status;
1348         WERROR result = WERR_OK;
1349         WERROR ignore;
1350         const char **enum_names = NULL;
1351         enum winreg_Type *enum_types = NULL;
1352         DATA_BLOB *enum_data_blobs = NULL;
1353         TALLOC_CTX *tmp_ctx;
1354
1355         tmp_ctx = talloc_stackframe();
1356         if (tmp_ctx == NULL) {
1357                 return WERR_NOMEM;
1358         }
1359
1360         path = winreg_printer_data_keyname(tmp_ctx, printer);
1361         if (path == NULL) {
1362                 TALLOC_FREE(tmp_ctx);
1363                 return WERR_NOMEM;
1364         }
1365
1366         result = winreg_printer_openkey(tmp_ctx,
1367                                         winreg_handle,
1368                                         path,
1369                                         "",
1370                                         false,
1371                                         access_mask,
1372                                         &hive_hnd,
1373                                         &key_hnd);
1374         if (!W_ERROR_IS_OK(result)) {
1375                 DEBUG(2, ("winreg_get_printer: Could not open key %s: %s\n",
1376                           path, win_errstr(result)));
1377                 goto done;
1378         }
1379
1380         status = dcerpc_winreg_enumvals(tmp_ctx,
1381                                         winreg_handle,
1382                                         &key_hnd,
1383                                         &num_values,
1384                                         &enum_names,
1385                                         &enum_types,
1386                                         &enum_data_blobs,
1387                                         &result);
1388         if (!NT_STATUS_IS_OK(status)){
1389                 result = ntstatus_to_werror(status);
1390         }
1391
1392         if (!W_ERROR_IS_OK(result)) {
1393                 DEBUG(0, ("winreg_get_printer: Could not enumerate values in %s: %s\n",
1394                           path, win_errstr(result)));
1395                 goto done;
1396         }
1397
1398         info2 = talloc_zero(tmp_ctx, struct spoolss_PrinterInfo2);
1399         if (info2 == NULL) {
1400                 result = WERR_NOMEM;
1401                 goto done;
1402         }
1403
1404         FILL_STRING(info2, EMPTY_STRING, info2->servername);
1405         FILL_STRING(info2, EMPTY_STRING, info2->printername);
1406         FILL_STRING(info2, EMPTY_STRING, info2->sharename);
1407         FILL_STRING(info2, EMPTY_STRING, info2->portname);
1408         FILL_STRING(info2, EMPTY_STRING, info2->drivername);
1409         FILL_STRING(info2, EMPTY_STRING, info2->comment);
1410         FILL_STRING(info2, EMPTY_STRING, info2->location);
1411         FILL_STRING(info2, EMPTY_STRING, info2->sepfile);
1412         FILL_STRING(info2, EMPTY_STRING, info2->printprocessor);
1413         FILL_STRING(info2, EMPTY_STRING, info2->datatype);
1414         FILL_STRING(info2, EMPTY_STRING, info2->parameters);
1415
1416         for (i = 0; i < num_values; i++) {
1417                 enum_value.value_name = enum_names[i];
1418                 enum_value.value_name_len = 2*strlen_m_term(enum_names[i]);
1419                 enum_value.type = enum_types[i];
1420                 enum_value.data_length = enum_data_blobs[i].length;
1421                 enum_value.data = NULL;
1422                 if (enum_value.data_length != 0){
1423                         enum_value.data = &enum_data_blobs[i];
1424                 }
1425                 v = &enum_value;
1426
1427                 result = winreg_enumval_to_sz(info2,
1428                                               v,
1429                                               "Name",
1430                                               &info2->printername);
1431                 CHECK_ERROR(result);
1432
1433                 result = winreg_enumval_to_sz(info2,
1434                                               v,
1435                                               "Share Name",
1436                                               &info2->sharename);
1437                 CHECK_ERROR(result);
1438
1439                 result = winreg_enumval_to_sz(info2,
1440                                               v,
1441                                               "Port",
1442                                               &info2->portname);
1443                 CHECK_ERROR(result);
1444
1445                 result = winreg_enumval_to_sz(info2,
1446                                               v,
1447                                               "Description",
1448                                               &info2->comment);
1449                 CHECK_ERROR(result);
1450
1451                 result = winreg_enumval_to_sz(info2,
1452                                               v,
1453                                               "Location",
1454                                               &info2->location);
1455                 CHECK_ERROR(result);
1456
1457                 result = winreg_enumval_to_sz(info2,
1458                                               v,
1459                                               "Separator File",
1460                                               &info2->sepfile);
1461                 CHECK_ERROR(result);
1462
1463                 result = winreg_enumval_to_sz(info2,
1464                                               v,
1465                                               "Print Processor",
1466                                               &info2->printprocessor);
1467                 CHECK_ERROR(result);
1468
1469                 result = winreg_enumval_to_sz(info2,
1470                                               v,
1471                                               "Datatype",
1472                                               &info2->datatype);
1473                 CHECK_ERROR(result);
1474
1475                 result = winreg_enumval_to_sz(info2,
1476                                               v,
1477                                               "Parameters",
1478                                               &info2->parameters);
1479                 CHECK_ERROR(result);
1480
1481                 result = winreg_enumval_to_sz(info2,
1482                                               v,
1483                                               "Printer Driver",
1484                                               &info2->drivername);
1485                 CHECK_ERROR(result);
1486
1487                 result = winreg_enumval_to_dword(info2,
1488                                                  v,
1489                                                  "Attributes",
1490                                                  &info2->attributes);
1491                 CHECK_ERROR(result);
1492
1493                 result = winreg_enumval_to_dword(info2,
1494                                                  v,
1495                                                  "Priority",
1496                                                  &info2->priority);
1497                 CHECK_ERROR(result);
1498
1499                 result = winreg_enumval_to_dword(info2,
1500                                                  v,
1501                                                  "Default Priority",
1502                                                  &info2->defaultpriority);
1503                 CHECK_ERROR(result);
1504
1505                 result = winreg_enumval_to_dword(info2,
1506                                                  v,
1507                                                  "StartTime",
1508                                                  &info2->starttime);
1509                 CHECK_ERROR(result);
1510
1511                 result = winreg_enumval_to_dword(info2,
1512                                                  v,
1513                                                  "UntilTime",
1514                                                  &info2->untiltime);
1515                 CHECK_ERROR(result);
1516
1517                 result = winreg_enumval_to_dword(info2,
1518                                                  v,
1519                                                  "Status",
1520                                                  &info2->status);
1521                 CHECK_ERROR(result);
1522
1523                 result = winreg_enumval_to_dword(info2,
1524                                                  v,
1525                                                  "StartTime",
1526                                                  &info2->starttime);
1527                 CHECK_ERROR(result);
1528         }
1529
1530         if (!W_ERROR_IS_OK(result)) {
1531                 DEBUG(0, ("winreg_get_printer: winreg_enumval_to_TYPE() failed "
1532                                         "for %s: %s\n",
1533                                         v->value_name,
1534                                         win_errstr(result)));
1535                 goto done;
1536         }
1537
1538         /* Construct the Device Mode */
1539         status = dcerpc_winreg_query_binary(tmp_ctx,
1540                                             winreg_handle,
1541                                             &key_hnd,
1542                                             "Default DevMode",
1543                                             &blob,
1544                                             &result);
1545         if (!NT_STATUS_IS_OK(status)) {
1546                 result = ntstatus_to_werror(status);
1547         }
1548         if (W_ERROR_IS_OK(result)) {
1549                 info2->devmode = talloc_zero(info2, struct spoolss_DeviceMode);
1550                 if (info2->devmode == NULL) {
1551                         result = WERR_NOMEM;
1552                         goto done;
1553                 }
1554                 ndr_err = ndr_pull_struct_blob(&blob,
1555                                                info2->devmode,
1556                                                info2->devmode,
1557                                                (ndr_pull_flags_fn_t) ndr_pull_spoolss_DeviceMode);
1558                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1559                         DEBUG(0, ("winreg_get_printer: Failed to unmarshall device mode\n"));
1560                         result = WERR_NOMEM;
1561                         goto done;
1562                 }
1563         }
1564
1565         if (info2->devmode == NULL && lp_default_devmode(snum)) {
1566                 result = spoolss_create_default_devmode(info2,
1567                                                         info2->printername,
1568                                                         &info2->devmode);
1569                 if (!W_ERROR_IS_OK(result)) {
1570                         goto done;
1571                 }
1572         }
1573
1574         if (info2->devmode) {
1575                 info2->devmode->size = ndr_size_spoolss_DeviceMode(info2->devmode, 0) - info2->devmode->driverextra_data.length;
1576         }
1577
1578         result = winreg_get_printer_secdesc(info2,
1579                                             winreg_handle,
1580                                             printer,
1581                                             &info2->secdesc);
1582         if (!W_ERROR_IS_OK(result)) {
1583                 goto done;
1584         }
1585
1586         /* Fix for OS/2 drivers. */
1587         if (get_remote_arch() == RA_OS2) {
1588                 spoolss_map_to_os2_driver(info2, &info2->drivername);
1589         }
1590
1591         if (pinfo2) {
1592                 *pinfo2 = talloc_move(mem_ctx, &info2);
1593         }
1594
1595         result = WERR_OK;
1596 done:
1597         if (is_valid_policy_hnd(&key_hnd)) {
1598                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1599         }
1600         if (is_valid_policy_hnd(&hive_hnd)) {
1601                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1602         }
1603
1604         TALLOC_FREE(tmp_ctx);
1605         return result;
1606 }
1607
1608 WERROR winreg_get_printer_secdesc(TALLOC_CTX *mem_ctx,
1609                                   struct dcerpc_binding_handle *winreg_handle,
1610                                   const char *sharename,
1611                                   struct spoolss_security_descriptor **psecdesc)
1612 {
1613         struct spoolss_security_descriptor *secdesc;
1614         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1615         struct policy_handle hive_hnd, key_hnd;
1616         const char *path;
1617         TALLOC_CTX *tmp_ctx;
1618         NTSTATUS status;
1619         WERROR result;
1620         WERROR ignore;
1621
1622         tmp_ctx = talloc_stackframe();
1623         if (tmp_ctx == NULL) {
1624                 return WERR_NOMEM;
1625         }
1626
1627         path = winreg_printer_data_keyname(tmp_ctx, sharename);
1628         if (path == NULL) {
1629                 talloc_free(tmp_ctx);
1630                 return WERR_NOMEM;
1631         }
1632
1633         ZERO_STRUCT(hive_hnd);
1634         ZERO_STRUCT(key_hnd);
1635
1636         result = winreg_printer_openkey(tmp_ctx,
1637                                         winreg_handle,
1638                                         path,
1639                                         "",
1640                                         false,
1641                                         access_mask,
1642                                         &hive_hnd,
1643                                         &key_hnd);
1644         if (!W_ERROR_IS_OK(result)) {
1645                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1646                         goto create_default;
1647                 }
1648                 goto done;
1649         }
1650
1651         status = dcerpc_winreg_query_sd(tmp_ctx,
1652                                         winreg_handle,
1653                                         &key_hnd,
1654                                         "Security",
1655                                         &secdesc,
1656                                         &result);
1657         if (!NT_STATUS_IS_OK(status)) {
1658                 result = ntstatus_to_werror(status);
1659         }
1660         if (!W_ERROR_IS_OK(result)) {
1661                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
1662
1663                         if (is_valid_policy_hnd(&key_hnd)) {
1664                                 dcerpc_winreg_CloseKey(winreg_handle,
1665                                                        tmp_ctx,
1666                                                        &key_hnd,
1667                                                        &ignore);
1668                         }
1669
1670                         if (is_valid_policy_hnd(&hive_hnd)) {
1671                                 dcerpc_winreg_CloseKey(winreg_handle,
1672                                                        tmp_ctx,
1673                                                        &hive_hnd,
1674                                                        &ignore);
1675                         }
1676                         goto create_default;
1677                 }
1678                 goto done;
1679         }
1680
1681         if (psecdesc) {
1682                 *psecdesc = talloc_move(mem_ctx, &secdesc);
1683         }
1684
1685         result = WERR_OK;
1686         goto done;
1687
1688 create_default:
1689         result = winreg_printer_openkey(tmp_ctx,
1690                                         winreg_handle,
1691                                         path,
1692                                         "",
1693                                         true,
1694                                         access_mask,
1695                                         &hive_hnd,
1696                                         &key_hnd);
1697         if (!W_ERROR_IS_OK(result)) {
1698                 goto done;
1699         }
1700
1701         result = spoolss_create_default_secdesc(tmp_ctx, &secdesc);
1702         if (!W_ERROR_IS_OK(result)) {
1703                 goto done;
1704         }
1705
1706         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
1707            this security descriptor has been created when winbindd was
1708            down.  Take ownership of security descriptor. */
1709         if (dom_sid_equal(secdesc->owner_sid, &global_sid_World)) {
1710                 struct dom_sid owner_sid;
1711
1712                 /* Change sd owner to workgroup administrator */
1713
1714                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
1715                         struct spoolss_security_descriptor *new_secdesc;
1716                         size_t size;
1717
1718                         /* Create new sd */
1719                         sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
1720
1721                         new_secdesc = make_sec_desc(tmp_ctx,
1722                                                     secdesc->revision,
1723                                                     secdesc->type,
1724                                                     &owner_sid,
1725                                                     secdesc->group_sid,
1726                                                     secdesc->sacl,
1727                                                     secdesc->dacl,
1728                                                     &size);
1729
1730                         if (new_secdesc == NULL) {
1731                                 result = WERR_NOMEM;
1732                                 goto done;
1733                         }
1734
1735                         /* Swap with other one */
1736                         secdesc = new_secdesc;
1737                 }
1738         }
1739
1740         status = dcerpc_winreg_set_sd(tmp_ctx,
1741                                           winreg_handle,
1742                                           &key_hnd,
1743                                           "Security",
1744                                           secdesc,
1745                                           &result);
1746         if (!NT_STATUS_IS_OK(status)) {
1747                 result = ntstatus_to_werror(status);
1748         }
1749         if (!W_ERROR_IS_OK(result)) {
1750                 return result;
1751         }
1752
1753         if (psecdesc) {
1754                 *psecdesc = talloc_move(mem_ctx, &secdesc);
1755         }
1756
1757         result = WERR_OK;
1758 done:
1759         if (is_valid_policy_hnd(&key_hnd)) {
1760                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1761         }
1762         if (is_valid_policy_hnd(&hive_hnd)) {
1763                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1764         }
1765
1766         talloc_free(tmp_ctx);
1767         return result;
1768 }
1769
1770 WERROR winreg_set_printer_secdesc(TALLOC_CTX *mem_ctx,
1771                                   struct dcerpc_binding_handle *winreg_handle,
1772                                   const char *sharename,
1773                                   const struct spoolss_security_descriptor *secdesc)
1774 {
1775         const struct spoolss_security_descriptor *new_secdesc = secdesc;
1776         struct spoolss_security_descriptor *old_secdesc;
1777         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1778         struct policy_handle hive_hnd, key_hnd;
1779         const char *path;
1780         TALLOC_CTX *tmp_ctx;
1781         NTSTATUS status;
1782         WERROR result;
1783         WERROR ignore;
1784
1785         tmp_ctx = talloc_stackframe();
1786         if (tmp_ctx == NULL) {
1787                 return WERR_NOMEM;
1788         }
1789
1790         path = winreg_printer_data_keyname(tmp_ctx, sharename);
1791         if (path == NULL) {
1792                 talloc_free(tmp_ctx);
1793                 return WERR_NOMEM;
1794         }
1795
1796         /*
1797          * The old owner and group sids of the security descriptor are not
1798          * present when new ACEs are added or removed by changing printer
1799          * permissions through NT.  If they are NULL in the new security
1800          * descriptor then copy them over from the old one.
1801          */
1802         if (!secdesc->owner_sid || !secdesc->group_sid) {
1803                 struct dom_sid *owner_sid, *group_sid;
1804                 struct security_acl *dacl, *sacl;
1805                 size_t size;
1806
1807                 result = winreg_get_printer_secdesc(tmp_ctx,
1808                                                     winreg_handle,
1809                                                     sharename,
1810                                                     &old_secdesc);
1811                 if (!W_ERROR_IS_OK(result)) {
1812                         talloc_free(tmp_ctx);
1813                         return result;
1814                 }
1815
1816                 /* Pick out correct owner and group sids */
1817                 owner_sid = secdesc->owner_sid ?
1818                             secdesc->owner_sid :
1819                             old_secdesc->owner_sid;
1820
1821                 group_sid = secdesc->group_sid ?
1822                             secdesc->group_sid :
1823                             old_secdesc->group_sid;
1824
1825                 dacl = secdesc->dacl ?
1826                        secdesc->dacl :
1827                        old_secdesc->dacl;
1828
1829                 sacl = secdesc->sacl ?
1830                        secdesc->sacl :
1831                        old_secdesc->sacl;
1832
1833                 /* Make a deep copy of the security descriptor */
1834                 new_secdesc = make_sec_desc(tmp_ctx,
1835                                             secdesc->revision,
1836                                             secdesc->type,
1837                                             owner_sid,
1838                                             group_sid,
1839                                             sacl,
1840                                             dacl,
1841                                             &size);
1842                 if (new_secdesc == NULL) {
1843                         talloc_free(tmp_ctx);
1844                         return WERR_NOMEM;
1845                 }
1846         }
1847
1848         ZERO_STRUCT(hive_hnd);
1849         ZERO_STRUCT(key_hnd);
1850
1851         result = winreg_printer_openkey(tmp_ctx,
1852                                         winreg_handle,
1853                                         path,
1854                                         "",
1855                                         false,
1856                                         access_mask,
1857                                         &hive_hnd,
1858                                         &key_hnd);
1859         if (!W_ERROR_IS_OK(result)) {
1860                 goto done;
1861         }
1862
1863         status = dcerpc_winreg_set_sd(tmp_ctx,
1864                                       winreg_handle,
1865                                       &key_hnd,
1866                                       "Security",
1867                                       new_secdesc,
1868                                       &result);
1869         if (!NT_STATUS_IS_OK(status)) {
1870                 result = ntstatus_to_werror(status);
1871         }
1872
1873 done:
1874         if (is_valid_policy_hnd(&key_hnd)) {
1875                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1876         }
1877         if (is_valid_policy_hnd(&hive_hnd)) {
1878                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1879         }
1880
1881         talloc_free(tmp_ctx);
1882         return result;
1883 }
1884
1885 /* Set printer data over the winreg pipe. */
1886 WERROR winreg_set_printer_dataex(TALLOC_CTX *mem_ctx,
1887                                  struct dcerpc_binding_handle *winreg_handle,
1888                                  const char *printer,
1889                                  const char *key,
1890                                  const char *value,
1891                                  enum winreg_Type type,
1892                                  uint8_t *data,
1893                                  uint32_t data_size)
1894 {
1895         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1896         struct policy_handle hive_hnd, key_hnd;
1897         struct winreg_String wvalue = { 0, };
1898         char *path;
1899         WERROR result = WERR_OK;
1900         WERROR ignore;
1901         NTSTATUS status;
1902         TALLOC_CTX *tmp_ctx;
1903
1904         tmp_ctx = talloc_stackframe();
1905         if (tmp_ctx == NULL) {
1906                 return WERR_NOMEM;
1907         }
1908
1909         path = winreg_printer_data_keyname(tmp_ctx, printer);
1910         if (path == NULL) {
1911                 TALLOC_FREE(tmp_ctx);
1912                 return WERR_NOMEM;
1913         }
1914
1915         ZERO_STRUCT(hive_hnd);
1916         ZERO_STRUCT(key_hnd);
1917
1918         DEBUG(8, ("winreg_set_printer_dataex: Open printer key %s, value %s, access_mask: 0x%05x for [%s]\n",
1919                         key, value, access_mask, printer));
1920         result = winreg_printer_openkey(tmp_ctx,
1921                                         winreg_handle,
1922                                         path,
1923                                         key,
1924                                         true,
1925                                         access_mask,
1926                                         &hive_hnd,
1927                                         &key_hnd);
1928         if (!W_ERROR_IS_OK(result)) {
1929                 DEBUG(0, ("winreg_set_printer_dataex: Could not open key %s: %s\n",
1930                           key, win_errstr(result)));
1931                 goto done;
1932         }
1933
1934         wvalue.name = value;
1935         status = dcerpc_winreg_SetValue(winreg_handle,
1936                                         tmp_ctx,
1937                                         &key_hnd,
1938                                         wvalue,
1939                                         type,
1940                                         data,
1941                                         data_size,
1942                                         &result);
1943         if (!NT_STATUS_IS_OK(status)) {
1944                 DEBUG(0, ("winreg_set_printer_dataex: Could not set value %s: %s\n",
1945                           value, nt_errstr(status)));
1946                 result = ntstatus_to_werror(status);
1947         }
1948
1949 done:
1950         if (is_valid_policy_hnd(&key_hnd)) {
1951                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
1952         }
1953         if (is_valid_policy_hnd(&hive_hnd)) {
1954                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
1955         }
1956
1957         TALLOC_FREE(tmp_ctx);
1958         return result;
1959 }
1960
1961 /* Get printer data over a winreg pipe. */
1962 WERROR winreg_get_printer_dataex(TALLOC_CTX *mem_ctx,
1963                                  struct dcerpc_binding_handle *winreg_handle,
1964                                  const char *printer,
1965                                  const char *key,
1966                                  const char *value,
1967                                  enum winreg_Type *type,
1968                                  uint8_t **data,
1969                                  uint32_t *data_size)
1970 {
1971         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1972         struct policy_handle hive_hnd, key_hnd;
1973         struct winreg_String wvalue;
1974         enum winreg_Type type_in = REG_NONE;
1975         char *path;
1976         uint8_t *data_in = NULL;
1977         uint32_t data_in_size = 0;
1978         uint32_t value_len = 0;
1979         WERROR result = WERR_OK;
1980         WERROR ignore;
1981         NTSTATUS status;
1982         TALLOC_CTX *tmp_ctx;
1983
1984         tmp_ctx = talloc_stackframe();
1985         if (tmp_ctx == NULL) {
1986                 return WERR_NOMEM;
1987         }
1988
1989         path = winreg_printer_data_keyname(tmp_ctx, printer);
1990         if (path == NULL) {
1991                 TALLOC_FREE(tmp_ctx);
1992                 return WERR_NOMEM;
1993         }
1994
1995         ZERO_STRUCT(hive_hnd);
1996         ZERO_STRUCT(key_hnd);
1997
1998         result = winreg_printer_openkey(tmp_ctx,
1999                                         winreg_handle,
2000                                         path,
2001                                         key,
2002                                         false,
2003                                         access_mask,
2004                                         &hive_hnd,
2005                                         &key_hnd);
2006         if (!W_ERROR_IS_OK(result)) {
2007                 DEBUG(2, ("winreg_get_printer_dataex: Could not open key %s: %s\n",
2008                           key, win_errstr(result)));
2009                 goto done;
2010         }
2011
2012         wvalue.name = value;
2013
2014         /*
2015          * call QueryValue once with data == NULL to get the
2016          * needed memory size to be allocated, then allocate
2017          * data buffer and call again.
2018          */
2019         status = dcerpc_winreg_QueryValue(winreg_handle,
2020                                           tmp_ctx,
2021                                           &key_hnd,
2022                                           &wvalue,
2023                                           &type_in,
2024                                           NULL,
2025                                           &data_in_size,
2026                                           &value_len,
2027                                           &result);
2028         if (!NT_STATUS_IS_OK(status)) {
2029                 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2030                           value, nt_errstr(status)));
2031                 result = ntstatus_to_werror(status);
2032                 goto done;
2033         }
2034         if (!W_ERROR_IS_OK(result)) {
2035                 DEBUG(2, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2036                           value, win_errstr(result)));
2037                 goto done;
2038         }
2039
2040         data_in = (uint8_t *) TALLOC(tmp_ctx, data_in_size);
2041         if (data_in == NULL) {
2042                 result = WERR_NOMEM;
2043                 goto done;
2044         }
2045         value_len = 0;
2046
2047         status = dcerpc_winreg_QueryValue(winreg_handle,
2048                                           tmp_ctx,
2049                                           &key_hnd,
2050                                           &wvalue,
2051                                           &type_in,
2052                                           data_in,
2053                                           &data_in_size,
2054                                           &value_len,
2055                                           &result);
2056         if (!NT_STATUS_IS_OK(status)) {
2057                 DEBUG(0, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2058                           value, nt_errstr(status)));
2059                 result = ntstatus_to_werror(status);
2060                 goto done;
2061         }
2062         if (!W_ERROR_IS_OK(result)) {
2063                 DEBUG(2, ("winreg_get_printer_dataex: Could not query value %s: %s\n",
2064                           value, win_errstr(result)));
2065                 goto done;
2066         }
2067
2068         *type = type_in;
2069         *data_size = data_in_size;
2070         if (data_in_size) {
2071                 *data = talloc_move(mem_ctx, &data_in);
2072         }
2073
2074         result = WERR_OK;
2075 done:
2076         if (is_valid_policy_hnd(&key_hnd)) {
2077                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2078         }
2079         if (is_valid_policy_hnd(&hive_hnd)) {
2080                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2081         }
2082
2083         TALLOC_FREE(tmp_ctx);
2084         return result;
2085 }
2086
2087 /* Enumerate on the values of a given key and provide the data. */
2088 WERROR winreg_enum_printer_dataex(TALLOC_CTX *mem_ctx,
2089                                   struct dcerpc_binding_handle *winreg_handle,
2090                                   const char *printer,
2091                                   const char *key,
2092                                   uint32_t *pnum_values,
2093                                   struct spoolss_PrinterEnumValues **penum_values)
2094 {
2095         uint32_t i;
2096         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2097         struct policy_handle hive_hnd, key_hnd;
2098
2099         struct spoolss_PrinterEnumValues *enum_values = NULL;
2100         uint32_t num_values = 0;
2101         char *path;
2102         WERROR result = WERR_OK;
2103         WERROR ignore;
2104         NTSTATUS status;
2105         const char **enum_names = NULL;
2106         enum winreg_Type *enum_types = NULL;
2107         DATA_BLOB *enum_data_blobs = NULL;
2108
2109         TALLOC_CTX *tmp_ctx;
2110
2111         tmp_ctx = talloc_stackframe();
2112         if (tmp_ctx == NULL) {
2113                 return WERR_NOMEM;
2114         }
2115
2116         path = winreg_printer_data_keyname(tmp_ctx, printer);
2117         if (path == NULL) {
2118                 TALLOC_FREE(tmp_ctx);
2119                 return WERR_NOMEM;
2120         }
2121
2122         result = winreg_printer_openkey(tmp_ctx,
2123                                         winreg_handle,
2124                                         path,
2125                                         key,
2126                                         false,
2127                                         access_mask,
2128                                         &hive_hnd,
2129                                         &key_hnd);
2130         if (!W_ERROR_IS_OK(result)) {
2131                 DEBUG(2, ("winreg_enum_printer_dataex: Could not open key %s: %s\n",
2132                           key, win_errstr(result)));
2133                 goto done;
2134         }
2135
2136         status = dcerpc_winreg_enumvals(tmp_ctx,
2137                                         winreg_handle,
2138                                         &key_hnd,
2139                                         &num_values,
2140                                         &enum_names,
2141                                         &enum_types,
2142                                         &enum_data_blobs,
2143                                         &result);
2144         if (!NT_STATUS_IS_OK(status)){
2145                 result = ntstatus_to_werror(status);
2146         }
2147
2148         if (!W_ERROR_IS_OK(result)) {
2149                 DEBUG(0, ("winreg_enum_printer_dataex: Could not enumerate values in %s: %s\n",
2150                           key, win_errstr(result)));
2151                 goto done;
2152         }
2153
2154         enum_values = talloc_array(tmp_ctx, struct spoolss_PrinterEnumValues, num_values);
2155         if (enum_values == NULL){
2156                 result = WERR_NOMEM;
2157                 DEBUG(0, ("winreg_enum_printer_dataex: Could not enumerate values in %s: %s\n",
2158                           key, win_errstr(result)));
2159                 goto done;
2160         }
2161
2162         for (i = 0; i < num_values; i++){
2163                 enum_values[i].value_name = enum_names[i];
2164                 enum_values[i].value_name_len = strlen_m_term(enum_names[i]) * 2;
2165                 enum_values[i].type = enum_types[i];
2166                 enum_values[i].data_length = enum_data_blobs[i].length;
2167                 enum_values[i].data = NULL;
2168
2169                 if (enum_values[i].data_length != 0){
2170                         enum_values[i].data = &enum_data_blobs[i];
2171                 }
2172         }
2173
2174         talloc_steal(enum_values, enum_names);
2175         talloc_steal(enum_values, enum_data_blobs);
2176
2177         *pnum_values = num_values;
2178         if (penum_values) {
2179                 *penum_values = talloc_move(mem_ctx, &enum_values);
2180         }
2181
2182         result = WERR_OK;
2183 done:
2184         if (is_valid_policy_hnd(&key_hnd)) {
2185                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2186         }
2187         if (is_valid_policy_hnd(&hive_hnd)) {
2188                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2189         }
2190
2191         TALLOC_FREE(tmp_ctx);
2192         return result;
2193 }
2194
2195 /* Delete printer data over a winreg pipe. */
2196 WERROR winreg_delete_printer_dataex(TALLOC_CTX *mem_ctx,
2197                                     struct dcerpc_binding_handle *winreg_handle,
2198                                     const char *printer,
2199                                     const char *key,
2200                                     const char *value)
2201 {
2202         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2203         struct policy_handle hive_hnd, key_hnd;
2204         struct winreg_String wvalue = { 0, };
2205         char *path;
2206         WERROR result = WERR_OK;
2207         WERROR ignore;
2208         NTSTATUS status;
2209
2210         TALLOC_CTX *tmp_ctx;
2211
2212         tmp_ctx = talloc_stackframe();
2213         if (tmp_ctx == NULL) {
2214                 return WERR_NOMEM;
2215         }
2216
2217         path = winreg_printer_data_keyname(tmp_ctx, printer);
2218         if (path == NULL) {
2219                 TALLOC_FREE(tmp_ctx);
2220                 return WERR_NOMEM;
2221         }
2222
2223         ZERO_STRUCT(hive_hnd);
2224         ZERO_STRUCT(key_hnd);
2225
2226         result = winreg_printer_openkey(tmp_ctx,
2227                                         winreg_handle,
2228                                         path,
2229                                         key,
2230                                         false,
2231                                         access_mask,
2232                                         &hive_hnd,
2233                                         &key_hnd);
2234         if (!W_ERROR_IS_OK(result)) {
2235                 DEBUG(0, ("winreg_delete_printer_dataex: Could not open key %s: %s\n",
2236                           key, win_errstr(result)));
2237                 goto done;
2238         }
2239
2240         wvalue.name = value;
2241         status = dcerpc_winreg_DeleteValue(winreg_handle,
2242                                            tmp_ctx,
2243                                            &key_hnd,
2244                                            wvalue,
2245                                            &result);
2246         if (!NT_STATUS_IS_OK(status)) {
2247                 DEBUG(0, ("winreg_delete_printer_dataex: Could not delete value %s: %s\n",
2248                           value, nt_errstr(status)));
2249                 result = ntstatus_to_werror(status);
2250         }
2251
2252 done:
2253         if (is_valid_policy_hnd(&key_hnd)) {
2254                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2255         }
2256         if (is_valid_policy_hnd(&hive_hnd)) {
2257                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2258         }
2259
2260         TALLOC_FREE(tmp_ctx);
2261         return result;
2262 }
2263
2264 /* Enumerate on the subkeys of a given key and provide the data. */
2265 WERROR winreg_enum_printer_key(TALLOC_CTX *mem_ctx,
2266                                struct dcerpc_binding_handle *winreg_handle,
2267                                const char *printer,
2268                                const char *key,
2269                                uint32_t *pnum_subkeys,
2270                                const char ***psubkeys)
2271 {
2272         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2273         struct policy_handle hive_hnd, key_hnd;
2274         char *path;
2275         const char **subkeys = NULL;
2276         uint32_t num_subkeys = -1;
2277
2278         WERROR result = WERR_OK;
2279         WERROR ignore;
2280         NTSTATUS status;
2281
2282         TALLOC_CTX *tmp_ctx;
2283
2284         tmp_ctx = talloc_stackframe();
2285         if (tmp_ctx == NULL) {
2286                 return WERR_NOMEM;
2287         }
2288
2289         path = winreg_printer_data_keyname(tmp_ctx, printer);
2290         if (path == NULL) {
2291                 TALLOC_FREE(tmp_ctx);
2292                 return WERR_NOMEM;
2293         }
2294
2295         ZERO_STRUCT(hive_hnd);
2296         ZERO_STRUCT(key_hnd);
2297
2298         result = winreg_printer_openkey(tmp_ctx,
2299                                         winreg_handle,
2300                                         path,
2301                                         key,
2302                                         false,
2303                                         access_mask,
2304                                         &hive_hnd,
2305                                         &key_hnd);
2306         if (!W_ERROR_IS_OK(result)) {
2307                 DEBUG(2, ("winreg_enum_printer_key: Could not open key %s: %s\n",
2308                           key, win_errstr(result)));
2309                 goto done;
2310         }
2311
2312         status = dcerpc_winreg_enum_keys(tmp_ctx,
2313                                          winreg_handle,
2314                                          &key_hnd,
2315                                          &num_subkeys,
2316                                          &subkeys,
2317                                          &result);
2318         if (!NT_STATUS_IS_OK(status)) {
2319                 result = ntstatus_to_werror(status);
2320         }
2321         if (!W_ERROR_IS_OK(result)) {
2322                 DEBUG(0, ("winreg_enum_printer_key: Could not enumerate subkeys in %s: %s\n",
2323                           key, win_errstr(result)));
2324                 goto done;
2325         }
2326
2327         *pnum_subkeys = num_subkeys;
2328         if (psubkeys) {
2329                 *psubkeys = talloc_move(mem_ctx, &subkeys);
2330         }
2331
2332         result = WERR_OK;
2333 done:
2334         if (is_valid_policy_hnd(&key_hnd)) {
2335                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2336         }
2337         if (is_valid_policy_hnd(&hive_hnd)) {
2338                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2339         }
2340
2341         TALLOC_FREE(tmp_ctx);
2342         return result;
2343 }
2344
2345 /* Delete a key with subkeys of a given printer. */
2346 WERROR winreg_delete_printer_key(TALLOC_CTX *mem_ctx,
2347                                  struct dcerpc_binding_handle *winreg_handle,
2348                                  const char *printer,
2349                                  const char *key)
2350 {
2351         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2352         struct policy_handle hive_hnd, key_hnd;
2353         char *keyname;
2354         char *path;
2355         WERROR result;
2356         WERROR ignore;
2357         NTSTATUS status;
2358         TALLOC_CTX *tmp_ctx;
2359
2360         tmp_ctx = talloc_stackframe();
2361         if (tmp_ctx == NULL) {
2362                 return WERR_NOMEM;
2363         }
2364
2365         path = winreg_printer_data_keyname(tmp_ctx, printer);
2366         if (path == NULL) {
2367                 TALLOC_FREE(tmp_ctx);
2368                 return WERR_NOMEM;
2369         }
2370
2371         result = winreg_printer_openkey(tmp_ctx,
2372                                         winreg_handle,
2373                                         path,
2374                                         key,
2375                                         false,
2376                                         access_mask,
2377                                         &hive_hnd,
2378                                         &key_hnd);
2379         if (!W_ERROR_IS_OK(result)) {
2380                 /* key doesn't exist */
2381                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2382                         result = WERR_OK;
2383                         goto done;
2384                 }
2385
2386                 DEBUG(0, ("winreg_delete_printer_key: Could not open key %s: %s\n",
2387                           key, win_errstr(result)));
2388                 goto done;
2389         }
2390
2391         if (is_valid_policy_hnd(&key_hnd)) {
2392                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &result);
2393         }
2394
2395         if (key == NULL || key[0] == '\0') {
2396                 keyname = path;
2397         } else {
2398                 keyname = talloc_asprintf(tmp_ctx,
2399                                           "%s\\%s",
2400                                           path,
2401                                           key);
2402                 if (keyname == NULL) {
2403                         result = WERR_NOMEM;
2404                         goto done;
2405                 }
2406         }
2407
2408         status = dcerpc_winreg_delete_subkeys_recursive(tmp_ctx,
2409                                                         winreg_handle,
2410                                                         &hive_hnd,
2411                                                         access_mask,
2412                                                         keyname,
2413                                                         &result);
2414
2415         if (!NT_STATUS_IS_OK(status)) {
2416                 DEBUG(0, ("winreg_delete_printer_key: Could not delete key %s: %s\n",
2417                           key, nt_errstr(status)));
2418                 result = ntstatus_to_werror(status);
2419                 goto done;
2420         }
2421
2422         if (!W_ERROR_IS_OK(result)) {
2423                 DEBUG(0, ("winreg_delete_printer_key: Could not delete key %s: %s\n",
2424                           key, win_errstr(result)));
2425                 goto done;
2426         }
2427
2428 done:
2429         if (is_valid_policy_hnd(&key_hnd)) {
2430                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2431         }
2432         if (is_valid_policy_hnd(&hive_hnd)) {
2433                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2434         }
2435
2436         TALLOC_FREE(tmp_ctx);
2437         return result;
2438 }
2439
2440 WERROR winreg_printer_update_changeid(TALLOC_CTX *mem_ctx,
2441                                       struct dcerpc_binding_handle *winreg_handle,
2442                                       const char *printer)
2443 {
2444         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2445         struct policy_handle hive_hnd, key_hnd;
2446         char *path;
2447         NTSTATUS status;
2448         WERROR result;
2449         WERROR ignore;
2450         TALLOC_CTX *tmp_ctx;
2451
2452         tmp_ctx = talloc_stackframe();
2453         if (tmp_ctx == NULL) {
2454                 return WERR_NOMEM;
2455         }
2456
2457         path = winreg_printer_data_keyname(tmp_ctx, printer);
2458         if (path == NULL) {
2459                 TALLOC_FREE(tmp_ctx);
2460                 return WERR_NOMEM;
2461         }
2462
2463         ZERO_STRUCT(hive_hnd);
2464         ZERO_STRUCT(key_hnd);
2465
2466         result = winreg_printer_openkey(tmp_ctx,
2467                                         winreg_handle,
2468                                         path,
2469                                         "",
2470                                         false,
2471                                         access_mask,
2472                                         &hive_hnd,
2473                                         &key_hnd);
2474         if (!W_ERROR_IS_OK(result)) {
2475                 DEBUG(0, ("winreg_printer_update_changeid: Could not open key %s: %s\n",
2476                           path, win_errstr(result)));
2477                 goto done;
2478         }
2479
2480         status = dcerpc_winreg_set_dword(tmp_ctx,
2481                                          winreg_handle,
2482                                          &key_hnd,
2483                                          "ChangeID",
2484                                          winreg_printer_rev_changeid(),
2485                                          &result);
2486         if (!NT_STATUS_IS_OK(status)) {
2487                 result = ntstatus_to_werror(status);
2488         }
2489         if (!W_ERROR_IS_OK(result)) {
2490                 goto done;
2491         }
2492
2493         result = WERR_OK;
2494 done:
2495         if (is_valid_policy_hnd(&key_hnd)) {
2496                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2497         }
2498         if (is_valid_policy_hnd(&hive_hnd)) {
2499                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2500         }
2501
2502         TALLOC_FREE(tmp_ctx);
2503         return result;
2504 }
2505
2506 WERROR winreg_printer_get_changeid(TALLOC_CTX *mem_ctx,
2507                                    struct dcerpc_binding_handle *winreg_handle,
2508                                    const char *printer,
2509                                    uint32_t *pchangeid)
2510 {
2511         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2512         struct policy_handle hive_hnd, key_hnd;
2513         uint32_t changeid = 0;
2514         char *path;
2515         NTSTATUS status;
2516         WERROR result;
2517         WERROR ignore;
2518         TALLOC_CTX *tmp_ctx;
2519
2520         tmp_ctx = talloc_stackframe();
2521         if (tmp_ctx == NULL) {
2522                 return WERR_NOMEM;
2523         }
2524
2525         path = winreg_printer_data_keyname(tmp_ctx, printer);
2526         if (path == NULL) {
2527                 TALLOC_FREE(tmp_ctx);
2528                 return WERR_NOMEM;
2529         }
2530
2531         ZERO_STRUCT(hive_hnd);
2532         ZERO_STRUCT(key_hnd);
2533
2534         result = winreg_printer_openkey(tmp_ctx,
2535                                         winreg_handle,
2536                                         path,
2537                                         "",
2538                                         false,
2539                                         access_mask,
2540                                         &hive_hnd,
2541                                         &key_hnd);
2542         if (!W_ERROR_IS_OK(result)) {
2543                 DEBUG(2, ("winreg_printer_get_changeid: Could not open key %s: %s\n",
2544                           path, win_errstr(result)));
2545                 goto done;
2546         }
2547
2548         DEBUG(10, ("winreg_printer_get_changeid: get changeid from %s\n", path));
2549
2550         status = dcerpc_winreg_query_dword(tmp_ctx,
2551                                            winreg_handle,
2552                                            &key_hnd,
2553                                            "ChangeID",
2554                                            &changeid,
2555                                            &result);
2556         if (!NT_STATUS_IS_OK(status)) {
2557                 result = ntstatus_to_werror(status);
2558         }
2559         if (!W_ERROR_IS_OK(result)) {
2560                 goto done;
2561         }
2562
2563         if (pchangeid) {
2564                 *pchangeid = changeid;
2565         }
2566
2567         result = WERR_OK;
2568 done:
2569         if (is_valid_policy_hnd(&key_hnd)) {
2570                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2571         }
2572         if (is_valid_policy_hnd(&hive_hnd)) {
2573                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2574         }
2575
2576         TALLOC_FREE(tmp_ctx);
2577         return result;
2578 }
2579
2580 /*
2581  * The special behaviour of the spoolss forms is documented at the website:
2582  *
2583  * Managing Win32 Printserver Forms
2584  * http://unixwiz.net/techtips/winspooler-forms.html
2585  */
2586
2587 WERROR winreg_printer_addform1(TALLOC_CTX *mem_ctx,
2588                                struct dcerpc_binding_handle *winreg_handle,
2589                                struct spoolss_AddFormInfo1 *form)
2590 {
2591         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2592         struct policy_handle hive_hnd, key_hnd;
2593         struct winreg_String wvalue = { 0, };
2594         DATA_BLOB blob;
2595         uint32_t num_info = 0;
2596         union spoolss_FormInfo *info = NULL;
2597         uint32_t i;
2598         WERROR result;
2599         WERROR ignore;
2600         NTSTATUS status;
2601         TALLOC_CTX *tmp_ctx;
2602
2603         tmp_ctx = talloc_stackframe();
2604         if (tmp_ctx == NULL) {
2605                 return WERR_NOMEM;
2606         }
2607
2608         ZERO_STRUCT(hive_hnd);
2609         ZERO_STRUCT(key_hnd);
2610
2611         result = winreg_printer_openkey(tmp_ctx,
2612                                         winreg_handle,
2613                                         TOP_LEVEL_CONTROL_FORMS_KEY,
2614                                         "",
2615                                         true,
2616                                         access_mask,
2617                                         &hive_hnd,
2618                                         &key_hnd);
2619         if (!W_ERROR_IS_OK(result)) {
2620                 DEBUG(0, ("winreg_printer_addform1: Could not open key %s: %s\n",
2621                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2622                 goto done;
2623         }
2624
2625         result = winreg_printer_enumforms1(tmp_ctx, winreg_handle,
2626                                            &num_info, &info);
2627         if (!W_ERROR_IS_OK(result)) {
2628                 DEBUG(0, ("winreg_printer_addform: Could not enum keys %s: %s\n",
2629                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2630                 goto done;
2631         }
2632
2633         /* If form name already exists or is builtin return ALREADY_EXISTS */
2634         for (i = 0; i < num_info; i++) {
2635                 if (strequal(info[i].info1.form_name, form->form_name)) {
2636                         result = WERR_FILE_EXISTS;
2637                         goto done;
2638                 }
2639         }
2640
2641         wvalue.name = form->form_name;
2642
2643         blob = data_blob_talloc(tmp_ctx, NULL, 32);
2644         SIVAL(blob.data,  0, form->size.width);
2645         SIVAL(blob.data,  4, form->size.height);
2646         SIVAL(blob.data,  8, form->area.left);
2647         SIVAL(blob.data, 12, form->area.top);
2648         SIVAL(blob.data, 16, form->area.right);
2649         SIVAL(blob.data, 20, form->area.bottom);
2650         SIVAL(blob.data, 24, num_info + 1); /* FIXME */
2651         SIVAL(blob.data, 28, form->flags);
2652
2653         status = dcerpc_winreg_SetValue(winreg_handle,
2654                                         tmp_ctx,
2655                                         &key_hnd,
2656                                         wvalue,
2657                                         REG_BINARY,
2658                                         blob.data,
2659                                         blob.length,
2660                                         &result);
2661         if (!NT_STATUS_IS_OK(status)) {
2662                 DEBUG(0, ("winreg_printer_addform1: Could not set value %s: %s\n",
2663                           wvalue.name, nt_errstr(status)));
2664                 result = ntstatus_to_werror(status);
2665         }
2666
2667 done:
2668         if (is_valid_policy_hnd(&key_hnd)) {
2669                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
2670         }
2671         if (is_valid_policy_hnd(&hive_hnd)) {
2672                 dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
2673         }
2674
2675         TALLOC_FREE(info);
2676         TALLOC_FREE(tmp_ctx);
2677         return result;
2678 }
2679
2680 WERROR winreg_printer_enumforms1(TALLOC_CTX *mem_ctx,
2681                                  struct dcerpc_binding_handle *winreg_handle,
2682                                  uint32_t *pnum_info,
2683                                  union spoolss_FormInfo **pinfo)
2684 {
2685         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2686         struct policy_handle hive_hnd, key_hnd;
2687         union spoolss_FormInfo *info;
2688         struct spoolss_PrinterEnumValues *enum_values = NULL;
2689         uint32_t num_values = 0;
2690         uint32_t num_builtin = ARRAY_SIZE(builtin_forms1);
2691         uint32_t i;
2692         WERROR result;
2693         WERROR ignore;
2694         NTSTATUS status;
2695         const char **enum_names = NULL;
2696         enum winreg_Type *enum_types = NULL;
2697         DATA_BLOB *enum_data_blobs = NULL;
2698         TALLOC_CTX *tmp_ctx;
2699
2700         tmp_ctx = talloc_stackframe();
2701         if (tmp_ctx == NULL) {
2702                 return WERR_NOMEM;
2703         }
2704
2705         ZERO_STRUCT(hive_hnd);
2706         ZERO_STRUCT(key_hnd);
2707
2708         result = winreg_printer_openkey(tmp_ctx,
2709                                         winreg_handle,
2710                                         TOP_LEVEL_CONTROL_FORMS_KEY,
2711                                         "",
2712                                         true,
2713                                         access_mask,
2714                                         &hive_hnd,
2715                                         &key_hnd);
2716         if (!W_ERROR_IS_OK(result)) {
2717                 /* key doesn't exist */
2718                 if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
2719                         result = WERR_OK;
2720                         goto done;
2721                 }
2722
2723                 DEBUG(0, ("winreg_printer_enumforms1: Could not open key %s: %s\n",
2724                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2725                 goto done;
2726         }
2727
2728         status = dcerpc_winreg_enumvals(tmp_ctx,
2729                                         winreg_handle,
2730                                         &key_hnd,
2731                                         &num_values,
2732                                         &enum_names,
2733                                         &enum_types,
2734                                         &enum_data_blobs,
2735                                         &result);
2736         if (!NT_STATUS_IS_OK(status)){
2737                 result = ntstatus_to_werror(status);
2738         }
2739
2740         if (!W_ERROR_IS_OK(result)) {
2741                 DEBUG(0, ("winreg_printer_enumforms1: Could not enumerate values in %s: %s\n",
2742                           TOP_LEVEL_CONTROL_FORMS_KEY, win_errstr(result)));
2743                 goto done;
2744         }
2745
2746         enum_values = talloc_zero_array(tmp_ctx,
2747                                         struct spoolss_PrinterEnumValues,
2748                                         num_values);
2749         if (enum_values == NULL){