Remove pwd_cache.c, it was doing nothing. Make user_name, domain, and
[nivanova/samba-autobuild/.git] / source3 / rpc_parse / parse_spoolss.c
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.
9  *
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.
14  *  
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.
19  *  
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/>.
22  */
23
24 #include "includes.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_RPC_PARSE
28
29
30 /*******************************************************************
31 This should be moved in a more generic lib.
32 ********************************************************************/  
33
34 bool spoolss_io_system_time(const char *desc, prs_struct *ps, int depth, SYSTEMTIME *systime)
35 {
36         if(!prs_uint16("year", ps, depth, &systime->year))
37                 return False;
38         if(!prs_uint16("month", ps, depth, &systime->month))
39                 return False;
40         if(!prs_uint16("dayofweek", ps, depth, &systime->dayofweek))
41                 return False;
42         if(!prs_uint16("day", ps, depth, &systime->day))
43                 return False;
44         if(!prs_uint16("hour", ps, depth, &systime->hour))
45                 return False;
46         if(!prs_uint16("minute", ps, depth, &systime->minute))
47                 return False;
48         if(!prs_uint16("second", ps, depth, &systime->second))
49                 return False;
50         if(!prs_uint16("milliseconds", ps, depth, &systime->milliseconds))
51                 return False;
52
53         return True;
54 }
55
56 /*******************************************************************
57 ********************************************************************/  
58
59 bool make_systemtime(SYSTEMTIME *systime, struct tm *unixtime)
60 {
61         systime->year=unixtime->tm_year+1900;
62         systime->month=unixtime->tm_mon+1;
63         systime->dayofweek=unixtime->tm_wday;
64         systime->day=unixtime->tm_mday;
65         systime->hour=unixtime->tm_hour;
66         systime->minute=unixtime->tm_min;
67         systime->second=unixtime->tm_sec;
68         systime->milliseconds=0;
69
70         return True;
71 }
72
73 /*******************************************************************
74  * read or write a DEVICEMODE struct.
75  * on reading allocate memory for the private member
76  ********************************************************************/
77
78 #define DM_NUM_OPTIONAL_FIELDS          8
79
80 bool spoolss_io_devmode(const char *desc, prs_struct *ps, int depth, DEVICEMODE *devmode)
81 {
82         int available_space;            /* size of the device mode left to parse */
83                                         /* only important on unmarshalling       */
84         int i = 0;
85         uint16 *unistr_buffer;
86         int j;
87                                         
88         struct optional_fields {
89                 fstring         name;
90                 uint32*         field;
91         } opt_fields[DM_NUM_OPTIONAL_FIELDS] = {
92                 { "icmmethod",          NULL },
93                 { "icmintent",          NULL },
94                 { "mediatype",          NULL },
95                 { "dithertype",         NULL },
96                 { "reserved1",          NULL },
97                 { "reserved2",          NULL },
98                 { "panningwidth",       NULL },
99                 { "panningheight",      NULL }
100         };
101
102         /* assign at run time to keep non-gcc compilers happy */
103
104         opt_fields[0].field = &devmode->icmmethod;
105         opt_fields[1].field = &devmode->icmintent;
106         opt_fields[2].field = &devmode->mediatype;
107         opt_fields[3].field = &devmode->dithertype;
108         opt_fields[4].field = &devmode->reserved1;
109         opt_fields[5].field = &devmode->reserved2;
110         opt_fields[6].field = &devmode->panningwidth;
111         opt_fields[7].field = &devmode->panningheight;
112                 
113         
114         prs_debug(ps, depth, desc, "spoolss_io_devmode");
115         depth++;
116
117         if (UNMARSHALLING(ps)) {
118                 devmode->devicename.buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
119                 if (devmode->devicename.buffer == NULL)
120                         return False;
121                 unistr_buffer = devmode->devicename.buffer;
122         }
123         else {
124                 /* devicename is a static sized string but the buffer we set is not */
125                 unistr_buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
126                 memset( unistr_buffer, 0x0, MAXDEVICENAME );
127                 for ( j=0; devmode->devicename.buffer[j]; j++ )
128                         unistr_buffer[j] = devmode->devicename.buffer[j];
129         }
130                 
131         if (!prs_uint16uni(True,"devicename", ps, depth, unistr_buffer, MAXDEVICENAME))
132                 return False;
133         
134         if (!prs_uint16("specversion",      ps, depth, &devmode->specversion))
135                 return False;
136                 
137         if (!prs_uint16("driverversion",    ps, depth, &devmode->driverversion))
138                 return False;
139         if (!prs_uint16("size",             ps, depth, &devmode->size))
140                 return False;
141         if (!prs_uint16("driverextra",      ps, depth, &devmode->driverextra))
142                 return False;
143         if (!prs_uint32("fields",           ps, depth, &devmode->fields))
144                 return False;
145         if (!prs_uint16("orientation",      ps, depth, &devmode->orientation))
146                 return False;
147         if (!prs_uint16("papersize",        ps, depth, &devmode->papersize))
148                 return False;
149         if (!prs_uint16("paperlength",      ps, depth, &devmode->paperlength))
150                 return False;
151         if (!prs_uint16("paperwidth",       ps, depth, &devmode->paperwidth))
152                 return False;
153         if (!prs_uint16("scale",            ps, depth, &devmode->scale))
154                 return False;
155         if (!prs_uint16("copies",           ps, depth, &devmode->copies))
156                 return False;
157         if (!prs_uint16("defaultsource",    ps, depth, &devmode->defaultsource))
158                 return False;
159         if (!prs_uint16("printquality",     ps, depth, &devmode->printquality))
160                 return False;
161         if (!prs_uint16("color",            ps, depth, &devmode->color))
162                 return False;
163         if (!prs_uint16("duplex",           ps, depth, &devmode->duplex))
164                 return False;
165         if (!prs_uint16("yresolution",      ps, depth, &devmode->yresolution))
166                 return False;
167         if (!prs_uint16("ttoption",         ps, depth, &devmode->ttoption))
168                 return False;
169         if (!prs_uint16("collate",          ps, depth, &devmode->collate))
170                 return False;
171
172         if (UNMARSHALLING(ps)) {
173                 devmode->formname.buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
174                 if (devmode->formname.buffer == NULL)
175                         return False;
176                 unistr_buffer = devmode->formname.buffer;
177         }
178         else {
179                 /* devicename is a static sized string but the buffer we set is not */
180                 unistr_buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
181                 memset( unistr_buffer, 0x0, MAXDEVICENAME );
182                 for ( j=0; devmode->formname.buffer[j]; j++ )
183                         unistr_buffer[j] = devmode->formname.buffer[j];
184         }
185         
186         if (!prs_uint16uni(True, "formname",  ps, depth, unistr_buffer, MAXDEVICENAME))
187                 return False;
188         if (!prs_uint16("logpixels",        ps, depth, &devmode->logpixels))
189                 return False;
190         if (!prs_uint32("bitsperpel",       ps, depth, &devmode->bitsperpel))
191                 return False;
192         if (!prs_uint32("pelswidth",        ps, depth, &devmode->pelswidth))
193                 return False;
194         if (!prs_uint32("pelsheight",       ps, depth, &devmode->pelsheight))
195                 return False;
196         if (!prs_uint32("displayflags",     ps, depth, &devmode->displayflags))
197                 return False;
198         if (!prs_uint32("displayfrequency", ps, depth, &devmode->displayfrequency))
199                 return False;
200         /* 
201          * every device mode I've ever seen on the wire at least has up 
202          * to the displayfrequency field.   --jerry (05-09-2002)
203          */
204          
205         /* add uint32's + uint16's + two UNICODE strings */
206          
207         available_space = devmode->size - (sizeof(uint32)*6 + sizeof(uint16)*18 + sizeof(uint16)*64);
208         
209         /* Sanity check - we only have uint32's left tp parse */
210         
211         if ( available_space && ((available_space % sizeof(uint32)) != 0) ) {
212                 DEBUG(0,("spoolss_io_devmode: available_space [%d] no in multiple of 4 bytes (size = %d)!\n",
213                         available_space, devmode->size));
214                 DEBUG(0,("spoolss_io_devmode: please report to samba-technical@samba.org!\n"));
215                 return False;
216         }
217
218         /* 
219          * Conditional parsing.  Assume that the DeviceMode has been 
220          * zero'd by the caller. 
221          */
222         
223         while ((available_space > 0)  && (i < DM_NUM_OPTIONAL_FIELDS))
224         {
225                 DEBUG(11, ("spoolss_io_devmode: [%d] bytes left to parse in devmode\n", available_space));
226                 if (!prs_uint32(opt_fields[i].name, ps, depth, opt_fields[i].field))
227                         return False;
228                 available_space -= sizeof(uint32);
229                 i++;
230         }        
231         
232         /* Sanity Check - we should no available space at this point unless 
233            MS changes the device mode structure */
234                 
235         if (available_space) {
236                 DEBUG(0,("spoolss_io_devmode: I've parsed all I know and there is still stuff left|\n"));
237                 DEBUG(0,("spoolss_io_devmode: available_space = [%d], devmode_size = [%d]!\n",
238                         available_space, devmode->size));
239                 DEBUG(0,("spoolss_io_devmode: please report to samba-technical@samba.org!\n"));
240                 return False;
241         }
242
243
244         if (devmode->driverextra!=0) {
245                 if (UNMARSHALLING(ps)) {
246                         devmode->dev_private=PRS_ALLOC_MEM(ps, uint8, devmode->driverextra);
247                         if(devmode->dev_private == NULL)
248                                 return False;
249                         DEBUG(7,("spoolss_io_devmode: allocated memory [%d] for dev_private\n",devmode->driverextra)); 
250                 }
251                         
252                 DEBUG(7,("spoolss_io_devmode: parsing [%d] bytes of dev_private\n",devmode->driverextra));
253                 if (!prs_uint8s(False, "dev_private",  ps, depth,
254                                 devmode->dev_private, devmode->driverextra))
255                         return False;
256         }
257
258         return True;
259 }
260
261 /*******************************************************************
262  * make a structure.
263  ********************************************************************/
264
265 bool make_spoolss_q_getprinterdata(SPOOL_Q_GETPRINTERDATA *q_u,
266                                    const POLICY_HND *handle,
267                                    const char *valuename, uint32 size)
268 {
269         if (q_u == NULL) return False;
270
271         DEBUG(5,("make_spoolss_q_getprinterdata\n"));
272
273         q_u->handle = *handle;
274         init_unistr2(&q_u->valuename, valuename, UNI_STR_TERMINATE);
275         q_u->size = size;
276
277         return True;
278 }
279
280 /*******************************************************************
281  * read a structure.
282  * called from spoolss_q_getprinterdata (srv_spoolss.c)
283  ********************************************************************/
284
285 bool spoolss_io_q_getprinterdata(const char *desc, SPOOL_Q_GETPRINTERDATA *q_u, prs_struct *ps, int depth)
286 {
287         if (q_u == NULL)
288                 return False;
289
290         prs_debug(ps, depth, desc, "spoolss_io_q_getprinterdata");
291         depth++;
292
293         if (!prs_align(ps))
294                 return False;
295         if (!smb_io_pol_hnd("printer handle",&q_u->handle,ps,depth))
296                 return False;
297         if (!prs_align(ps))
298                 return False;
299         if (!smb_io_unistr2("valuename", &q_u->valuename,True,ps,depth))
300                 return False;
301         if (!prs_align(ps))
302                 return False;
303         if (!prs_uint32("size", ps, depth, &q_u->size))
304                 return False;
305
306         return True;
307 }
308
309 /*******************************************************************
310  * write a structure.
311  * called from spoolss_r_getprinterdata (srv_spoolss.c)
312  ********************************************************************/
313
314 bool spoolss_io_r_getprinterdata(const char *desc, SPOOL_R_GETPRINTERDATA *r_u, prs_struct *ps, int depth)
315 {
316         if (r_u == NULL)
317                 return False;
318
319         prs_debug(ps, depth, desc, "spoolss_io_r_getprinterdata");
320         depth++;
321
322         if (!prs_align(ps))
323                 return False;
324         if (!prs_uint32("type", ps, depth, &r_u->type))
325                 return False;
326         if (!prs_uint32("size", ps, depth, &r_u->size))
327                 return False;
328         
329         if (UNMARSHALLING(ps) && r_u->size) {
330                 r_u->data = PRS_ALLOC_MEM(ps, unsigned char, r_u->size);
331                 if(!r_u->data)
332                         return False;
333         }
334
335         if (!prs_uint8s( False, "data", ps, depth, r_u->data, r_u->size ))
336                 return False;
337                 
338         if (!prs_align(ps))
339                 return False;
340         
341         if (!prs_uint32("needed", ps, depth, &r_u->needed))
342                 return False;
343         if (!prs_werror("status", ps, depth, &r_u->status))
344                 return False;
345                 
346         return True;
347 }
348
349 /*******************************************************************
350  * return the length of a uint32 (obvious, but the code is clean)
351  ********************************************************************/
352
353 static uint32 size_of_uint32(uint32 *value)
354 {
355         return (sizeof(*value));
356 }
357
358 /*******************************************************************
359 return the size required by a struct in the stream
360 ********************************************************************/  
361 uint32 spoolss_size_printer_enum_values(PRINTER_ENUM_VALUES *p)
362 {
363         uint32  size = 0; 
364         
365         if (!p)
366                 return 0;
367         
368         /* uint32(offset) + uint32(length) + length) */
369         size += (size_of_uint32(&p->value_len)*2) + p->value_len;
370         size += (size_of_uint32(&p->data_len)*2) + p->data_len + (p->data_len%2) ;
371         
372         size += size_of_uint32(&p->type);
373                        
374         return size;
375 }
376
377 /*******************************************************************
378  make a BUFFER5 struct from a uint16*
379  ******************************************************************/
380
381 bool make_spoolss_buffer5(TALLOC_CTX *mem_ctx, BUFFER5 *buf5, uint32 len, uint16 *src)
382 {
383
384         buf5->buf_len = len;
385         if (src) {
386                 if (len) {
387                         if((buf5->buffer=(uint16*)TALLOC_MEMDUP(mem_ctx, src, sizeof(uint16)*len)) == NULL) {
388                                 DEBUG(0,("make_spoolss_buffer5: Unable to malloc memory for buffer!\n"));
389                                 return False;
390                         }
391                 } else {
392                         buf5->buffer = NULL;
393                 }
394         } else {
395                 buf5->buffer=NULL;
396         }
397         
398         return True;
399 }
400
401 /*******************************************************************
402 ********************************************************************/  
403
404 bool spoolss_io_r_enumprinterdata(const char *desc, SPOOL_R_ENUMPRINTERDATA *r_u, prs_struct *ps, int depth)
405 {       
406         prs_debug(ps, depth, desc, "spoolss_io_r_enumprinterdata");
407         depth++;
408
409         if(!prs_align(ps))
410                 return False;
411         if(!prs_uint32("valuesize", ps, depth, &r_u->valuesize))
412                 return False;
413
414         if (UNMARSHALLING(ps) && r_u->valuesize) {
415                 r_u->value = PRS_ALLOC_MEM(ps, uint16, r_u->valuesize);
416                 if (!r_u->value) {
417                         DEBUG(0, ("spoolss_io_r_enumprinterdata: out of memory for printerdata value\n"));
418                         return False;
419                 }
420         }
421
422         if(!prs_uint16uni(False, "value", ps, depth, r_u->value, r_u->valuesize ))
423                 return False;
424
425         if(!prs_align(ps))
426                 return False;
427
428         if(!prs_uint32("realvaluesize", ps, depth, &r_u->realvaluesize))
429                 return False;
430
431         if(!prs_uint32("type", ps, depth, &r_u->type))
432                 return False;
433
434         if(!prs_uint32("datasize", ps, depth, &r_u->datasize))
435                 return False;
436
437         if (UNMARSHALLING(ps) && r_u->datasize) {
438                 r_u->data = PRS_ALLOC_MEM(ps, uint8, r_u->datasize);
439                 if (!r_u->data) {
440                         DEBUG(0, ("spoolss_io_r_enumprinterdata: out of memory for printerdata data\n"));
441                         return False;
442                 }
443         }
444
445         if(!prs_uint8s(False, "data", ps, depth, r_u->data, r_u->datasize))
446                 return False;
447         if(!prs_align(ps))
448                 return False;
449
450         if(!prs_uint32("realdatasize", ps, depth, &r_u->realdatasize))
451                 return False;
452         if(!prs_werror("status", ps, depth, &r_u->status))
453                 return False;
454
455         return True;
456 }
457
458 /*******************************************************************
459 ********************************************************************/  
460
461 bool spoolss_io_q_enumprinterdata(const char *desc, SPOOL_Q_ENUMPRINTERDATA *q_u, prs_struct *ps, int depth)
462 {
463         prs_debug(ps, depth, desc, "spoolss_io_q_enumprinterdata");
464         depth++;
465
466         if(!prs_align(ps))
467                 return False;
468         if(!smb_io_pol_hnd("printer handle",&q_u->handle,ps,depth))
469                 return False;
470         if(!prs_uint32("index", ps, depth, &q_u->index))
471                 return False;
472         if(!prs_uint32("valuesize", ps, depth, &q_u->valuesize))
473                 return False;
474         if(!prs_uint32("datasize", ps, depth, &q_u->datasize))
475                 return False;
476
477         return True;
478 }
479
480 /*******************************************************************
481 ********************************************************************/  
482
483 bool make_spoolss_q_enumprinterdata(SPOOL_Q_ENUMPRINTERDATA *q_u,
484                 const POLICY_HND *hnd,
485                 uint32 idx, uint32 valuelen, uint32 datalen)
486 {
487         memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
488         q_u->index=idx;
489         q_u->valuesize=valuelen;
490         q_u->datasize=datalen;
491
492         return True;
493 }
494
495 /*******************************************************************
496 ********************************************************************/  
497
498 bool make_spoolss_q_enumprinterdataex(SPOOL_Q_ENUMPRINTERDATAEX *q_u,
499                                       const POLICY_HND *hnd, const char *key,
500                                       uint32 size)
501 {
502         memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
503         init_unistr2(&q_u->key, key, UNI_STR_TERMINATE);
504         q_u->size = size;
505
506         return True;
507 }
508
509 /*******************************************************************
510 ********************************************************************/  
511 bool make_spoolss_q_setprinterdata(SPOOL_Q_SETPRINTERDATA *q_u, const POLICY_HND *hnd,
512                                    char* value, uint32 data_type, char* data, uint32 data_size)
513 {
514         memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
515         q_u->type = data_type;
516         init_unistr2(&q_u->value, value, UNI_STR_TERMINATE);
517
518         q_u->max_len = q_u->real_len = data_size;
519         q_u->data = (unsigned char *)data;
520         
521         return True;
522 }
523
524 /*******************************************************************
525 ********************************************************************/  
526
527 bool spoolss_io_q_setprinterdata(const char *desc, SPOOL_Q_SETPRINTERDATA *q_u, prs_struct *ps, int depth)
528 {
529         prs_debug(ps, depth, desc, "spoolss_io_q_setprinterdata");
530         depth++;
531
532         if(!prs_align(ps))
533                 return False;
534         if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth))
535                 return False;
536         if(!smb_io_unistr2("", &q_u->value, True, ps, depth))
537                 return False;
538
539         if(!prs_align(ps))
540                 return False;
541
542         if(!prs_uint32("type", ps, depth, &q_u->type))
543                 return False;
544
545         if(!prs_uint32("max_len", ps, depth, &q_u->max_len))
546                 return False;
547
548         switch (q_u->type)
549         {
550                 case REG_SZ:
551                 case REG_BINARY:
552                 case REG_DWORD:
553                 case REG_MULTI_SZ:
554                         if (q_u->max_len) {
555                                 if (UNMARSHALLING(ps))
556                                         q_u->data=PRS_ALLOC_MEM(ps, uint8, q_u->max_len);
557                                 if(q_u->data == NULL)
558                                         return False;
559                                 if(!prs_uint8s(False,"data", ps, depth, q_u->data, q_u->max_len))
560                                         return False;
561                         }
562                         if(!prs_align(ps))
563                                 return False;
564                         break;
565         }       
566         
567         if(!prs_uint32("real_len", ps, depth, &q_u->real_len))
568                 return False;
569
570         return True;
571 }
572
573 /*******************************************************************
574 ********************************************************************/  
575
576 bool spoolss_io_r_setprinterdata(const char *desc, SPOOL_R_SETPRINTERDATA *r_u, prs_struct *ps, int depth)
577 {
578         prs_debug(ps, depth, desc, "spoolss_io_r_setprinterdata");
579         depth++;
580
581         if(!prs_align(ps))
582                 return False;
583         if(!prs_werror("status",     ps, depth, &r_u->status))
584                 return False;
585
586         return True;
587 }
588
589 /*******************************************************************
590  * read a structure.
591  ********************************************************************/  
592 bool make_spoolss_q_enumprinterkey(SPOOL_Q_ENUMPRINTERKEY *q_u, 
593                                    POLICY_HND *hnd, const char *key, 
594                                    uint32 size)
595 {
596         DEBUG(5,("make_spoolss_q_enumprinterkey\n"));
597
598         memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
599         init_unistr2(&q_u->key, key, UNI_STR_TERMINATE);
600         q_u->size = size;
601
602         return True;
603 }
604
605 /*******************************************************************
606  * read a structure.
607  ********************************************************************/  
608
609 bool spoolss_io_q_enumprinterkey(const char *desc, SPOOL_Q_ENUMPRINTERKEY *q_u, prs_struct *ps, int depth)
610 {
611         prs_debug(ps, depth, desc, "spoolss_io_q_enumprinterkey");
612         depth++;
613
614         if(!prs_align(ps))
615                 return False;
616         if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth))
617                 return False;
618                 
619         if(!smb_io_unistr2("", &q_u->key, True, ps, depth))
620                 return False;
621
622         if(!prs_align(ps))
623                 return False;
624         
625         if(!prs_uint32("size", ps, depth, &q_u->size))
626                 return False;
627
628         return True;
629 }
630
631 /*******************************************************************
632  * write a structure.
633  ********************************************************************/  
634
635 bool spoolss_io_r_enumprinterkey(const char *desc, SPOOL_R_ENUMPRINTERKEY *r_u, prs_struct *ps, int depth)
636 {
637         prs_debug(ps, depth, desc, "spoolss_io_r_enumprinterkey");
638         depth++;
639
640         if(!prs_align(ps))
641                 return False;
642
643         if (!smb_io_buffer5("", &r_u->keys, ps, depth))
644                 return False;
645         
646         if(!prs_align(ps))
647                 return False;
648
649         if(!prs_uint32("needed",     ps, depth, &r_u->needed))
650                 return False;
651
652         if(!prs_werror("status",     ps, depth, &r_u->status))
653                 return False;
654
655         return True;
656 }
657
658 /*******************************************************************
659  * read a structure.
660  ********************************************************************/  
661
662 bool spoolss_io_q_enumprinterdataex(const char *desc, SPOOL_Q_ENUMPRINTERDATAEX *q_u, prs_struct *ps, int depth)
663 {
664         prs_debug(ps, depth, desc, "spoolss_io_q_enumprinterdataex");
665         depth++;
666
667         if(!prs_align(ps))
668                 return False;
669         if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth))
670                 return False;
671                 
672         if(!smb_io_unistr2("", &q_u->key, True, ps, depth))
673                 return False;
674
675         if(!prs_align(ps))
676                 return False;
677         
678         if(!prs_uint32("size", ps, depth, &q_u->size))
679                 return False;
680
681         return True;
682 }
683
684 /*******************************************************************
685 ********************************************************************/  
686
687 static bool spoolss_io_printer_enum_values_ctr(const char *desc, prs_struct *ps, 
688                                 PRINTER_ENUM_VALUES_CTR *ctr, int depth)
689 {
690         int     i;
691         uint32  valuename_offset,
692                 data_offset,
693                 current_offset;
694         const uint32 basic_unit = 20; /* size of static portion of enum_values */
695
696         prs_debug(ps, depth, desc, "spoolss_io_printer_enum_values_ctr");
697         depth++;        
698
699         /* 
700          * offset data begins at 20 bytes per structure * size_of_array.
701          * Don't forget the uint32 at the beginning 
702          * */
703         
704         current_offset = basic_unit * ctr->size_of_array;
705         
706         /* first loop to write basic enum_value information */
707         
708         if (UNMARSHALLING(ps) && ctr->size_of_array) {
709                 ctr->values = PRS_ALLOC_MEM(ps, PRINTER_ENUM_VALUES, ctr->size_of_array);
710                 if (!ctr->values)
711                         return False;
712         }
713
714         for (i=0; i<ctr->size_of_array; i++) {
715                 uint32 base_offset, return_offset;
716
717                 base_offset = prs_offset(ps);
718
719                 valuename_offset = current_offset;
720                 if (!prs_uint32("valuename_offset", ps, depth, &valuename_offset))
721                         return False;
722
723                 /* Read or write the value. */
724
725                 return_offset = prs_offset(ps);
726
727                 if (!prs_set_offset(ps, base_offset + valuename_offset)) {
728                         return False;
729                 }
730
731                 if (!prs_unistr("valuename", ps, depth, &ctr->values[i].valuename))
732                         return False;
733
734                 /* And go back. */
735                 if (!prs_set_offset(ps, return_offset))
736                         return False;
737
738                 if (!prs_uint32("value_len", ps, depth, &ctr->values[i].value_len))
739                         return False;
740         
741                 if (!prs_uint32("type", ps, depth, &ctr->values[i].type))
742                         return False;
743         
744                 data_offset = ctr->values[i].value_len + valuename_offset;
745                 
746                 if (!prs_uint32("data_offset", ps, depth, &data_offset))
747                         return False;
748
749                 if (!prs_uint32("data_len", ps, depth, &ctr->values[i].data_len))
750                         return False;
751                         
752                 /* Read or write the data. */
753
754                 return_offset = prs_offset(ps);
755
756                 if (!prs_set_offset(ps, base_offset + data_offset)) {
757                         return False;
758                 }
759
760                 if ( ctr->values[i].data_len ) {
761                         if ( UNMARSHALLING(ps) ) {
762                                 ctr->values[i].data = PRS_ALLOC_MEM(ps, uint8, ctr->values[i].data_len);
763                                 if (!ctr->values[i].data)
764                                         return False;
765                         }
766                         if (!prs_uint8s(False, "data", ps, depth, ctr->values[i].data, ctr->values[i].data_len))
767                                 return False;
768                 }
769
770                 current_offset  = data_offset + ctr->values[i].data_len - basic_unit;
771                 /* account for 2 byte alignment */
772                 current_offset += (current_offset % 2);
773
774                 /* Remember how far we got. */
775                 data_offset = prs_offset(ps);
776
777                 /* And go back. */
778                 if (!prs_set_offset(ps, return_offset))
779                         return False;
780
781         }
782
783         /* Go to the last data offset we got to. */
784
785         if (!prs_set_offset(ps, data_offset))
786                 return False;
787
788         /* And ensure we're 2 byte aligned. */
789
790         if ( !prs_align_uint16(ps) )
791                 return False;
792
793         return True;    
794 }
795
796 /*******************************************************************
797  * write a structure.
798  ********************************************************************/  
799
800 bool spoolss_io_r_enumprinterdataex(const char *desc, SPOOL_R_ENUMPRINTERDATAEX *r_u, prs_struct *ps, int depth)
801 {
802         uint32 data_offset, end_offset;
803         prs_debug(ps, depth, desc, "spoolss_io_r_enumprinterdataex");
804         depth++;
805
806         if(!prs_align(ps))
807                 return False;
808
809         if (!prs_uint32("size", ps, depth, &r_u->ctr.size))
810                 return False;
811
812         data_offset = prs_offset(ps);
813
814         if (!prs_set_offset(ps, data_offset + r_u->ctr.size))
815                 return False;
816
817         if(!prs_align(ps))
818                 return False;
819
820         if(!prs_uint32("needed",     ps, depth, &r_u->needed))
821                 return False;
822
823         if(!prs_uint32("returned",   ps, depth, &r_u->returned))
824                 return False;
825
826         if(!prs_werror("status",     ps, depth, &r_u->status))
827                 return False;
828
829         r_u->ctr.size_of_array = r_u->returned;
830
831         end_offset = prs_offset(ps);
832
833         if (!prs_set_offset(ps, data_offset))
834                 return False;
835
836         if (r_u->ctr.size)
837                 if (!spoolss_io_printer_enum_values_ctr("", ps, &r_u->ctr, depth ))
838                         return False;
839
840         if (!prs_set_offset(ps, end_offset))
841                 return False;
842         return True;
843 }