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