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/>.
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 */
42 uint16
*unistr_buffer
;
45 struct optional_fields
{
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");
74 if (UNMARSHALLING(ps
)) {
75 devmode
->devicename
.buffer
= PRS_ALLOC_MEM(ps
, uint16
, MAXDEVICENAME
);
76 if (devmode
->devicename
.buffer
== NULL
)
78 unistr_buffer
= devmode
->devicename
.buffer
;
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
))
91 if (!prs_uint16("specversion", ps
, depth
, &devmode
->specversion
))
94 if (!prs_uint16("driverversion", ps
, depth
, &devmode
->driverversion
))
96 if (!prs_uint16("size", ps
, depth
, &devmode
->size
))
98 if (!prs_uint16("driverextra", ps
, depth
, &devmode
->driverextra
))
100 if (!prs_uint32("fields", ps
, depth
, &devmode
->fields
))
102 if (!prs_uint16("orientation", ps
, depth
, &devmode
->orientation
))
104 if (!prs_uint16("papersize", ps
, depth
, &devmode
->papersize
))
106 if (!prs_uint16("paperlength", ps
, depth
, &devmode
->paperlength
))
108 if (!prs_uint16("paperwidth", ps
, depth
, &devmode
->paperwidth
))
110 if (!prs_uint16("scale", ps
, depth
, &devmode
->scale
))
112 if (!prs_uint16("copies", ps
, depth
, &devmode
->copies
))
114 if (!prs_uint16("defaultsource", ps
, depth
, &devmode
->defaultsource
))
116 if (!prs_uint16("printquality", ps
, depth
, &devmode
->printquality
))
118 if (!prs_uint16("color", ps
, depth
, &devmode
->color
))
120 if (!prs_uint16("duplex", ps
, depth
, &devmode
->duplex
))
122 if (!prs_uint16("yresolution", ps
, depth
, &devmode
->yresolution
))
124 if (!prs_uint16("ttoption", ps
, depth
, &devmode
->ttoption
))
126 if (!prs_uint16("collate", ps
, depth
, &devmode
->collate
))
129 if (UNMARSHALLING(ps
)) {
130 devmode
->formname
.buffer
= PRS_ALLOC_MEM(ps
, uint16
, MAXDEVICENAME
);
131 if (devmode
->formname
.buffer
== NULL
)
133 unistr_buffer
= devmode
->formname
.buffer
;
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
))
145 if (!prs_uint16("logpixels", ps
, depth
, &devmode
->logpixels
))
147 if (!prs_uint32("bitsperpel", ps
, depth
, &devmode
->bitsperpel
))
149 if (!prs_uint32("pelswidth", ps
, depth
, &devmode
->pelswidth
))
151 if (!prs_uint32("pelsheight", ps
, depth
, &devmode
->pelsheight
))
153 if (!prs_uint32("displayflags", ps
, depth
, &devmode
->displayflags
))
155 if (!prs_uint32("displayfrequency", ps
, depth
, &devmode
->displayfrequency
))
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"));
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
))
185 available_space
-= sizeof(uint32
);
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"));
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
)
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
))
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
)
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
);
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
)
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"));
270 /*******************************************************************
271 ********************************************************************/
273 bool make_spoolss_q_enumprinterdataex(SPOOL_Q_ENUMPRINTERDATAEX
*q_u
,
274 const POLICY_HND
*hnd
, const char *key
,
277 memcpy(&q_u
->handle
, hnd
, sizeof(q_u
->handle
));
278 init_unistr2(&q_u
->key
, key
, UNI_STR_TERMINATE
);
284 /*******************************************************************
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");
295 if(!smb_io_pol_hnd("printer handle", &q_u
->handle
, ps
, depth
))
298 if(!smb_io_unistr2("", &q_u
->key
, True
, ps
, depth
))
304 if(!prs_uint32("size", ps
, depth
, &q_u
->size
))
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
)
317 uint32 valuename_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");
326 * offset data begins at 20 bytes per structure * size_of_array.
327 * Don't forget the uint32 at the beginning
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
);
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
))
349 /* Read or write the value. */
351 return_offset
= prs_offset(ps
);
353 if (!prs_set_offset(ps
, base_offset
+ valuename_offset
)) {
357 if (!prs_unistr("valuename", ps
, depth
, &ctr
->values
[i
].valuename
))
361 if (!prs_set_offset(ps
, return_offset
))
364 if (!prs_uint32("value_len", ps
, depth
, &ctr
->values
[i
].value_len
))
367 if (!prs_uint32("type", ps
, depth
, &ctr
->values
[i
].type
))
370 data_offset
= ctr
->values
[i
].value_len
+ valuename_offset
;
372 if (!prs_uint32("data_offset", ps
, depth
, &data_offset
))
375 if (!prs_uint32("data_len", ps
, depth
, &ctr
->values
[i
].data_len
))
378 /* Read or write the data. */
380 return_offset
= prs_offset(ps
);
382 if (!prs_set_offset(ps
, base_offset
+ data_offset
)) {
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
)
392 if (!prs_uint8s(False
, "data", ps
, depth
, ctr
->values
[i
].data
, ctr
->values
[i
].data_len
))
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
);
404 if (!prs_set_offset(ps
, return_offset
))
409 /* Go to the last data offset we got to. */
411 if (!prs_set_offset(ps
, data_offset
))
414 /* And ensure we're 2 byte aligned. */
416 if ( !prs_align_uint16(ps
) )
422 /*******************************************************************
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");
435 if (!prs_uint32("size", ps
, depth
, &r_u
->ctr
.size
))
438 data_offset
= prs_offset(ps
);
440 if (!prs_set_offset(ps
, data_offset
+ r_u
->ctr
.size
))
446 if(!prs_uint32("needed", ps
, depth
, &r_u
->needed
))
449 if(!prs_uint32("returned", ps
, depth
, &r_u
->returned
))
452 if(!prs_werror("status", ps
, depth
, &r_u
->status
))
455 r_u
->ctr
.size_of_array
= r_u
->returned
;
457 end_offset
= prs_offset(ps
);
459 if (!prs_set_offset(ps
, data_offset
))
463 if (!spoolss_io_printer_enum_values_ctr("", ps
, &r_u
->ctr
, depth
))
466 if (!prs_set_offset(ps
, end_offset
))