s3-spoolss: move SYSTEMTIME parsing to a more generic place, as suggested.
[Samba.git] / source3 / rpc_parse / parse_spoolss.c
blobc082af6f099a728a7c582e5f65ba39856020de01
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Gerald Carter 2000-2002,
8 * Copyright (C) Tim Potter 2001-2002.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_RPC_PARSE
30 /*******************************************************************
31 * read or write a DEVICEMODE struct.
32 * on reading allocate memory for the private member
33 ********************************************************************/
35 #define DM_NUM_OPTIONAL_FIELDS 8
37 bool spoolss_io_devmode(const char *desc, prs_struct *ps, int depth, DEVICEMODE *devmode)
39 int available_space; /* size of the device mode left to parse */
40 /* only important on unmarshalling */
41 int i = 0;
42 uint16 *unistr_buffer;
43 int j;
45 struct optional_fields {
46 fstring name;
47 uint32* field;
48 } opt_fields[DM_NUM_OPTIONAL_FIELDS] = {
49 { "icmmethod", NULL },
50 { "icmintent", NULL },
51 { "mediatype", NULL },
52 { "dithertype", NULL },
53 { "reserved1", NULL },
54 { "reserved2", NULL },
55 { "panningwidth", NULL },
56 { "panningheight", NULL }
59 /* assign at run time to keep non-gcc compilers happy */
61 opt_fields[0].field = &devmode->icmmethod;
62 opt_fields[1].field = &devmode->icmintent;
63 opt_fields[2].field = &devmode->mediatype;
64 opt_fields[3].field = &devmode->dithertype;
65 opt_fields[4].field = &devmode->reserved1;
66 opt_fields[5].field = &devmode->reserved2;
67 opt_fields[6].field = &devmode->panningwidth;
68 opt_fields[7].field = &devmode->panningheight;
71 prs_debug(ps, depth, desc, "spoolss_io_devmode");
72 depth++;
74 if (UNMARSHALLING(ps)) {
75 devmode->devicename.buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
76 if (devmode->devicename.buffer == NULL)
77 return False;
78 unistr_buffer = devmode->devicename.buffer;
80 else {
81 /* devicename is a static sized string but the buffer we set is not */
82 unistr_buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
83 memset( unistr_buffer, 0x0, MAXDEVICENAME );
84 for ( j=0; devmode->devicename.buffer[j]; j++ )
85 unistr_buffer[j] = devmode->devicename.buffer[j];
88 if (!prs_uint16uni(True,"devicename", ps, depth, unistr_buffer, MAXDEVICENAME))
89 return False;
91 if (!prs_uint16("specversion", ps, depth, &devmode->specversion))
92 return False;
94 if (!prs_uint16("driverversion", ps, depth, &devmode->driverversion))
95 return False;
96 if (!prs_uint16("size", ps, depth, &devmode->size))
97 return False;
98 if (!prs_uint16("driverextra", ps, depth, &devmode->driverextra))
99 return False;
100 if (!prs_uint32("fields", ps, depth, &devmode->fields))
101 return False;
102 if (!prs_uint16("orientation", ps, depth, &devmode->orientation))
103 return False;
104 if (!prs_uint16("papersize", ps, depth, &devmode->papersize))
105 return False;
106 if (!prs_uint16("paperlength", ps, depth, &devmode->paperlength))
107 return False;
108 if (!prs_uint16("paperwidth", ps, depth, &devmode->paperwidth))
109 return False;
110 if (!prs_uint16("scale", ps, depth, &devmode->scale))
111 return False;
112 if (!prs_uint16("copies", ps, depth, &devmode->copies))
113 return False;
114 if (!prs_uint16("defaultsource", ps, depth, &devmode->defaultsource))
115 return False;
116 if (!prs_uint16("printquality", ps, depth, &devmode->printquality))
117 return False;
118 if (!prs_uint16("color", ps, depth, &devmode->color))
119 return False;
120 if (!prs_uint16("duplex", ps, depth, &devmode->duplex))
121 return False;
122 if (!prs_uint16("yresolution", ps, depth, &devmode->yresolution))
123 return False;
124 if (!prs_uint16("ttoption", ps, depth, &devmode->ttoption))
125 return False;
126 if (!prs_uint16("collate", ps, depth, &devmode->collate))
127 return False;
129 if (UNMARSHALLING(ps)) {
130 devmode->formname.buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
131 if (devmode->formname.buffer == NULL)
132 return False;
133 unistr_buffer = devmode->formname.buffer;
135 else {
136 /* devicename is a static sized string but the buffer we set is not */
137 unistr_buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
138 memset( unistr_buffer, 0x0, MAXDEVICENAME );
139 for ( j=0; devmode->formname.buffer[j]; j++ )
140 unistr_buffer[j] = devmode->formname.buffer[j];
143 if (!prs_uint16uni(True, "formname", ps, depth, unistr_buffer, MAXDEVICENAME))
144 return False;
145 if (!prs_uint16("logpixels", ps, depth, &devmode->logpixels))
146 return False;
147 if (!prs_uint32("bitsperpel", ps, depth, &devmode->bitsperpel))
148 return False;
149 if (!prs_uint32("pelswidth", ps, depth, &devmode->pelswidth))
150 return False;
151 if (!prs_uint32("pelsheight", ps, depth, &devmode->pelsheight))
152 return False;
153 if (!prs_uint32("displayflags", ps, depth, &devmode->displayflags))
154 return False;
155 if (!prs_uint32("displayfrequency", ps, depth, &devmode->displayfrequency))
156 return False;
158 * every device mode I've ever seen on the wire at least has up
159 * to the displayfrequency field. --jerry (05-09-2002)
162 /* add uint32's + uint16's + two UNICODE strings */
164 available_space = devmode->size - (sizeof(uint32)*6 + sizeof(uint16)*18 + sizeof(uint16)*64);
166 /* Sanity check - we only have uint32's left tp parse */
168 if ( available_space && ((available_space % sizeof(uint32)) != 0) ) {
169 DEBUG(0,("spoolss_io_devmode: available_space [%d] no in multiple of 4 bytes (size = %d)!\n",
170 available_space, devmode->size));
171 DEBUG(0,("spoolss_io_devmode: please report to samba-technical@samba.org!\n"));
172 return False;
176 * Conditional parsing. Assume that the DeviceMode has been
177 * zero'd by the caller.
180 while ((available_space > 0) && (i < DM_NUM_OPTIONAL_FIELDS))
182 DEBUG(11, ("spoolss_io_devmode: [%d] bytes left to parse in devmode\n", available_space));
183 if (!prs_uint32(opt_fields[i].name, ps, depth, opt_fields[i].field))
184 return False;
185 available_space -= sizeof(uint32);
186 i++;
189 /* Sanity Check - we should no available space at this point unless
190 MS changes the device mode structure */
192 if (available_space) {
193 DEBUG(0,("spoolss_io_devmode: I've parsed all I know and there is still stuff left|\n"));
194 DEBUG(0,("spoolss_io_devmode: available_space = [%d], devmode_size = [%d]!\n",
195 available_space, devmode->size));
196 DEBUG(0,("spoolss_io_devmode: please report to samba-technical@samba.org!\n"));
197 return False;
201 if (devmode->driverextra!=0) {
202 if (UNMARSHALLING(ps)) {
203 devmode->dev_private=PRS_ALLOC_MEM(ps, uint8, devmode->driverextra);
204 if(devmode->dev_private == NULL)
205 return False;
206 DEBUG(7,("spoolss_io_devmode: allocated memory [%d] for dev_private\n",devmode->driverextra));
209 DEBUG(7,("spoolss_io_devmode: parsing [%d] bytes of dev_private\n",devmode->driverextra));
210 if (!prs_uint8s(False, "dev_private", ps, depth,
211 devmode->dev_private, devmode->driverextra))
212 return False;
215 return True;
218 /*******************************************************************
219 * return the length of a uint32 (obvious, but the code is clean)
220 ********************************************************************/
222 static uint32 size_of_uint32(uint32 *value)
224 return (sizeof(*value));
227 /*******************************************************************
228 return the size required by a struct in the stream
229 ********************************************************************/
230 uint32 spoolss_size_printer_enum_values(PRINTER_ENUM_VALUES *p)
232 uint32 size = 0;
234 if (!p)
235 return 0;
237 /* uint32(offset) + uint32(length) + length) */
238 size += (size_of_uint32(&p->value_len)*2) + p->value_len;
239 size += (size_of_uint32(&p->data_len)*2) + p->data_len + (p->data_len%2) ;
241 size += size_of_uint32(&p->type);
243 return size;
246 /*******************************************************************
247 make a BUFFER5 struct from a uint16*
248 ******************************************************************/
250 bool make_spoolss_buffer5(TALLOC_CTX *mem_ctx, BUFFER5 *buf5, uint32 len, uint16 *src)
253 buf5->buf_len = len;
254 if (src) {
255 if (len) {
256 if((buf5->buffer=(uint16*)TALLOC_MEMDUP(mem_ctx, src, sizeof(uint16)*len)) == NULL) {
257 DEBUG(0,("make_spoolss_buffer5: Unable to malloc memory for buffer!\n"));
258 return False;
260 } else {
261 buf5->buffer = NULL;
263 } else {
264 buf5->buffer=NULL;
267 return True;
270 /*******************************************************************
271 ********************************************************************/
273 bool make_spoolss_q_enumprinterdataex(SPOOL_Q_ENUMPRINTERDATAEX *q_u,
274 const POLICY_HND *hnd, const char *key,
275 uint32 size)
277 memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
278 init_unistr2(&q_u->key, key, UNI_STR_TERMINATE);
279 q_u->size = size;
281 return True;
284 /*******************************************************************
285 * read a structure.
286 ********************************************************************/
288 bool spoolss_io_q_enumprinterdataex(const char *desc, SPOOL_Q_ENUMPRINTERDATAEX *q_u, prs_struct *ps, int depth)
290 prs_debug(ps, depth, desc, "spoolss_io_q_enumprinterdataex");
291 depth++;
293 if(!prs_align(ps))
294 return False;
295 if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth))
296 return False;
298 if(!smb_io_unistr2("", &q_u->key, True, ps, depth))
299 return False;
301 if(!prs_align(ps))
302 return False;
304 if(!prs_uint32("size", ps, depth, &q_u->size))
305 return False;
307 return True;
310 /*******************************************************************
311 ********************************************************************/
313 static bool spoolss_io_printer_enum_values_ctr(const char *desc, prs_struct *ps,
314 PRINTER_ENUM_VALUES_CTR *ctr, int depth)
316 int i;
317 uint32 valuename_offset,
318 data_offset,
319 current_offset;
320 const uint32 basic_unit = 20; /* size of static portion of enum_values */
322 prs_debug(ps, depth, desc, "spoolss_io_printer_enum_values_ctr");
323 depth++;
326 * offset data begins at 20 bytes per structure * size_of_array.
327 * Don't forget the uint32 at the beginning
328 * */
330 current_offset = basic_unit * ctr->size_of_array;
332 /* first loop to write basic enum_value information */
334 if (UNMARSHALLING(ps) && ctr->size_of_array) {
335 ctr->values = PRS_ALLOC_MEM(ps, PRINTER_ENUM_VALUES, ctr->size_of_array);
336 if (!ctr->values)
337 return False;
340 for (i=0; i<ctr->size_of_array; i++) {
341 uint32 base_offset, return_offset;
343 base_offset = prs_offset(ps);
345 valuename_offset = current_offset;
346 if (!prs_uint32("valuename_offset", ps, depth, &valuename_offset))
347 return False;
349 /* Read or write the value. */
351 return_offset = prs_offset(ps);
353 if (!prs_set_offset(ps, base_offset + valuename_offset)) {
354 return False;
357 if (!prs_unistr("valuename", ps, depth, &ctr->values[i].valuename))
358 return False;
360 /* And go back. */
361 if (!prs_set_offset(ps, return_offset))
362 return False;
364 if (!prs_uint32("value_len", ps, depth, &ctr->values[i].value_len))
365 return False;
367 if (!prs_uint32("type", ps, depth, &ctr->values[i].type))
368 return False;
370 data_offset = ctr->values[i].value_len + valuename_offset;
372 if (!prs_uint32("data_offset", ps, depth, &data_offset))
373 return False;
375 if (!prs_uint32("data_len", ps, depth, &ctr->values[i].data_len))
376 return False;
378 /* Read or write the data. */
380 return_offset = prs_offset(ps);
382 if (!prs_set_offset(ps, base_offset + data_offset)) {
383 return False;
386 if ( ctr->values[i].data_len ) {
387 if ( UNMARSHALLING(ps) ) {
388 ctr->values[i].data = PRS_ALLOC_MEM(ps, uint8, ctr->values[i].data_len);
389 if (!ctr->values[i].data)
390 return False;
392 if (!prs_uint8s(False, "data", ps, depth, ctr->values[i].data, ctr->values[i].data_len))
393 return False;
396 current_offset = data_offset + ctr->values[i].data_len - basic_unit;
397 /* account for 2 byte alignment */
398 current_offset += (current_offset % 2);
400 /* Remember how far we got. */
401 data_offset = prs_offset(ps);
403 /* And go back. */
404 if (!prs_set_offset(ps, return_offset))
405 return False;
409 /* Go to the last data offset we got to. */
411 if (!prs_set_offset(ps, data_offset))
412 return False;
414 /* And ensure we're 2 byte aligned. */
416 if ( !prs_align_uint16(ps) )
417 return False;
419 return True;
422 /*******************************************************************
423 * write a structure.
424 ********************************************************************/
426 bool spoolss_io_r_enumprinterdataex(const char *desc, SPOOL_R_ENUMPRINTERDATAEX *r_u, prs_struct *ps, int depth)
428 uint32 data_offset, end_offset;
429 prs_debug(ps, depth, desc, "spoolss_io_r_enumprinterdataex");
430 depth++;
432 if(!prs_align(ps))
433 return False;
435 if (!prs_uint32("size", ps, depth, &r_u->ctr.size))
436 return False;
438 data_offset = prs_offset(ps);
440 if (!prs_set_offset(ps, data_offset + r_u->ctr.size))
441 return False;
443 if(!prs_align(ps))
444 return False;
446 if(!prs_uint32("needed", ps, depth, &r_u->needed))
447 return False;
449 if(!prs_uint32("returned", ps, depth, &r_u->returned))
450 return False;
452 if(!prs_werror("status", ps, depth, &r_u->status))
453 return False;
455 r_u->ctr.size_of_array = r_u->returned;
457 end_offset = prs_offset(ps);
459 if (!prs_set_offset(ps, data_offset))
460 return False;
462 if (r_u->ctr.size)
463 if (!spoolss_io_printer_enum_values_ctr("", ps, &r_u->ctr, depth ))
464 return False;
466 if (!prs_set_offset(ps, end_offset))
467 return False;
468 return True;