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