#ifndef RPCCLIENT_TEST
[kai/samba.git] / source3 / rpc_parse / parse_prs.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba memory buffer functions
5    Copyright (C) Andrew Tridgell              1992-1997
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1997
7    Copyright (C) Jeremy Allison 1999.
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 extern int DEBUGLEVEL;
25
26 #include "includes.h"
27
28
29 /*******************************************************************
30 dump a prs to a file
31  ********************************************************************/
32 void prs_dump(char *name, int v, prs_struct *ps)
33 {
34         int fd, i;
35         pstring fname;
36         if (DEBUGLEVEL < 50) return;
37         for (i=1;i<100;i++) {
38                 if (v != -1) {
39                         slprintf(fname,sizeof(fname), "/tmp/%s_%d.%d.prs", name, v, i);
40                 } else {
41                         slprintf(fname,sizeof(fname), "/tmp/%s.%d.prs", name, i);
42                 }
43                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
44                 if (fd != -1 || errno != EEXIST) break;
45         }
46         if (fd != -1) {
47                 write(fd, ps->data_p + ps->data_offset, ps->grow_size - ps->data_offset);
48                 close(fd);
49                 DEBUG(0,("created %s\n", fname));
50         }
51 }
52
53
54
55 /*******************************************************************
56  debug output for parsing info.
57
58  XXXX side-effect of this function is to increase the debug depth XXXX
59
60  ********************************************************************/
61 void prs_debug(prs_struct *ps, int depth, char *desc, char *fn_name)
62 {
63         DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->data_offset, fn_name, desc));
64 }
65
66
67 /*******************************************************************
68  Initialise a parse structure - malloc the data if requested.
69  ********************************************************************/
70 BOOL prs_init(prs_struct *ps, uint32 size, uint8 align, BOOL io)
71 {
72         ZERO_STRUCTP(ps);
73         ps->io = io;
74         ps->bigendian_data = False;
75         ps->align = align;
76         ps->is_dynamic = False;
77         ps->data_offset = 0;
78         ps->buffer_size = 0;
79         ps->data_p = NULL;
80
81         if (size != 0) {
82                 ps->buffer_size = size;
83                 if((ps->data_p = (char *)malloc((size_t)size)) == NULL) {
84                         DEBUG(0,("prs_init: malloc fail for %u bytes.\n", (unsigned int)size));
85                         return False;
86                 }
87                 ps->is_dynamic = True; /* We own this memory. */
88         }
89
90         return True;
91 }
92
93 /*******************************************************************
94  read from a socket into memory.
95  ********************************************************************/
96 BOOL prs_read(prs_struct *ps, int fd, size_t len, int timeout)
97 {
98         BOOL ok;
99         size_t prev_size = ps->buffer_size;
100         if (!prs_grow(ps, len))
101         {
102                 return False;
103         }
104
105         if (timeout > 0)
106         {
107                 ok = (read_with_timeout(fd, &ps->data_p[prev_size],
108                                             len, len,timeout) == len);
109         }
110         else 
111         {
112                 ok = (read_data(fd, &ps->data_p[prev_size], len) == len);
113         }
114         return ok;
115 }
116
117 /*******************************************************************
118  Delete the memory in a parse structure - if we own it.
119  ********************************************************************/
120
121 void prs_mem_free(prs_struct *ps)
122 {
123         if(ps->is_dynamic && (ps->data_p != NULL))
124                 free(ps->data_p);
125         ps->is_dynamic = False;
126         ps->data_p = NULL;
127         ps->buffer_size = 0;
128         ps->data_offset = 0;
129 }
130
131 /*******************************************************************
132  Hand some already allocated memory to a prs_struct.
133  ********************************************************************/
134
135 void prs_give_memory(prs_struct *ps, char *buf, uint32 size, BOOL is_dynamic)
136 {
137         ps->is_dynamic = is_dynamic;
138         ps->data_p = buf;
139         ps->buffer_size = size;
140 }
141
142 /*******************************************************************
143  Take some memory back from a prs_struct.
144  ********************************************************************/
145
146 char *prs_take_memory(prs_struct *ps, uint32 *psize)
147 {
148         char *ret = ps->data_p;
149         if(psize)
150                 *psize = ps->buffer_size;
151         ps->is_dynamic = False;
152         prs_mem_free(ps);
153         return ret;
154 }
155
156 /*******************************************************************
157  Set a prs_struct to exactly a given size. Will grow or tuncate if neccessary.
158  ********************************************************************/
159
160 BOOL prs_set_buffer_size(prs_struct *ps, uint32 newsize)
161 {
162         if (newsize > ps->buffer_size)
163                 return prs_force_grow(ps, newsize - ps->buffer_size);
164
165         if (newsize < ps->buffer_size) {
166                 char *new_data_p = Realloc(ps->data_p, newsize);
167                 /* if newsize is zero, Realloc acts like free() & returns NULL*/
168                 if (new_data_p == NULL && newsize != 0) {
169                         DEBUG(0,("prs_set_buffer_size: Realloc failure for size %u.\n",
170                                 (unsigned int)newsize));
171                         DEBUG(0,("prs_set_buffer_size: Reason %s\n",strerror(errno)));
172                         return False;
173                 }
174                 ps->data_p = new_data_p;
175                 ps->buffer_size = newsize;
176         }
177
178         return True;
179 }
180
181 /*******************************************************************
182  Attempt, if needed, to grow a data buffer.
183  Also depends on the data stream mode (io).
184  ********************************************************************/
185
186 BOOL prs_grow(prs_struct *ps, uint32 extra_space)
187 {
188         uint32 new_size;
189         char *new_data;
190
191         ps->grow_size = MAX(ps->grow_size, ps->data_offset + extra_space);
192
193         if(ps->data_offset + extra_space <= ps->buffer_size)
194                 return True;
195
196         /*
197          * We cannot grow the buffer if we're not reading
198          * into the prs_struct, or if we don't own the memory.
199          */
200
201         if(UNMARSHALLING(ps) || !ps->is_dynamic) {
202                 DEBUG(0,("prs_grow: Buffer overflow - unable to expand buffer by %u bytes.\n",
203                                 (unsigned int)extra_space));
204                 return False;
205         }
206         
207         /*
208          * Decide how much extra space we really need.
209          */
210
211         extra_space -= (ps->buffer_size - ps->data_offset);
212         if(ps->buffer_size == 0) {
213                 /*
214                  * Ensure we have at least a PDU's length, or extra_space, whichever
215                  * is greater.
216                  */
217
218                 new_size = MAX(MAX_PDU_FRAG_LEN,extra_space);
219
220                 if((new_data = malloc(new_size)) == NULL) {
221                         DEBUG(0,("prs_grow: Malloc failure for size %u.\n", (unsigned int)new_size));
222                         return False;
223                 }
224                 memset(new_data, '\0', new_size );
225         } else {
226                 /*
227                  * If the current buffer size is bigger than the space needed, just 
228                  * double it, else add extra_space.
229                  */
230                 new_size = MAX(ps->buffer_size*2, ps->buffer_size + extra_space);               
231
232                 if ((new_data = Realloc(ps->data_p, new_size)) == NULL) {
233                         DEBUG(0,("prs_grow: Realloc failure for size %u.\n",
234                                 (unsigned int)new_size));
235                         return False;
236                 }
237
238                 memset(&new_data[ps->buffer_size], '\0', new_size - ps->buffer_size);
239         }
240         ps->buffer_size = new_size;
241         ps->data_p = new_data;
242
243         return True;
244 }
245
246 /*******************************************************************
247  Attempt to force a data buffer to grow by len bytes.
248  This is only used when appending more data onto a prs_struct
249  when reading an rpc reply, before unmarshalling it.
250  ********************************************************************/
251
252 BOOL prs_force_grow(prs_struct *ps, uint32 extra_space)
253 {
254         uint32 new_size = ps->buffer_size + extra_space;
255         char *new_data;
256
257         if(!UNMARSHALLING(ps) || !ps->is_dynamic) {
258                 DEBUG(0,("prs_force_grow: Buffer overflow - unable to expand buffer by %u bytes.\n",
259                                 (unsigned int)extra_space));
260                 return False;
261         }
262
263         if((new_data = Realloc(ps->data_p, new_size)) == NULL) {
264                 DEBUG(0,("prs_force_grow: Realloc failure for size %u.\n",
265                         (unsigned int)new_size));
266                 return False;
267         }
268
269         memset(&new_data[ps->buffer_size], '\0', new_size - ps->buffer_size);
270
271         ps->buffer_size = new_size;
272         ps->data_p = new_data;
273
274         return True;
275 }
276
277 /*******************************************************************
278  Get the data pointer (external interface).
279  ********************************************************************/
280
281 char *prs_data_p(prs_struct *ps)
282 {
283         return ps->data_p;
284 }
285
286 /*******************************************************************
287  Get the current data size (external interface).
288  ********************************************************************/
289
290 uint32 prs_data_size(prs_struct *ps)
291 {
292         return ps->buffer_size;
293 }
294
295 /*******************************************************************
296  Fetch the current offset (external interface).
297  ********************************************************************/
298
299 uint32 prs_offset(prs_struct *ps)
300 {
301         return ps->data_offset;
302 }
303
304 /*******************************************************************
305  Set the current offset (external interface).
306  ********************************************************************/
307
308 BOOL prs_set_offset(prs_struct *ps, uint32 offset)
309 {
310         if(offset <= ps->data_offset) {
311                 ps->data_offset = offset;
312                 return True;
313         }
314
315         if(!prs_grow(ps, offset - ps->data_offset))
316                 return False;
317
318         ps->data_offset = offset;
319         return True;
320 }
321
322 /*******************************************************************
323  Append the data from one parse_struct into another.
324  ********************************************************************/
325
326 BOOL prs_append_prs_data(prs_struct *dst, prs_struct *src)
327 {
328         if(!prs_grow(dst, prs_offset(src)))
329                 return False;
330
331         memcpy(&dst->data_p[dst->data_offset], prs_data_p(src), (size_t)prs_offset(src));
332         dst->data_offset += prs_offset(src);
333
334         return True;
335 }
336
337 /*******************************************************************
338  Append some data from one parse_struct into another.
339  ********************************************************************/
340
341 BOOL prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start, uint32 len)
342 {       
343         if (len == 0)
344                 return True;
345
346         if(!prs_grow(dst, len))
347                 return False;
348         
349         memcpy(&dst->data_p[dst->data_offset], prs_data_p(src)+start, (size_t)len);
350         dst->data_offset += len;
351
352         return True;
353 }
354
355 /*******************************************************************
356  Append the data from a buffer into a parse_struct.
357  ********************************************************************/
358
359 BOOL prs_append_data(prs_struct *dst, char *src, uint32 len)
360 {
361         if(!prs_grow(dst, len))
362                 return False;
363
364         memcpy(&dst->data_p[dst->data_offset], src, (size_t)len);
365         dst->data_offset += len;
366
367         return True;
368 }
369
370 /*******************************************************************
371  Set the data as big-endian (external interface).
372  ********************************************************************/
373
374 void prs_set_bigendian_data(prs_struct *ps)
375 {
376         ps->bigendian_data = True;
377 }
378
379 /*******************************************************************
380  Align a the data_len to a multiple of align bytes - filling with
381  zeros.
382  ********************************************************************/
383
384 BOOL prs_align(prs_struct *ps)
385 {
386         uint32 mod = ps->data_offset & (ps->align-1);
387
388         if (ps->align != 0 && mod != 0) {
389                 uint32 extra_space = (ps->align - mod);
390                 if(!prs_grow(ps, extra_space))
391                         return False;
392                 memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space);
393                 ps->data_offset += extra_space;
394         }
395
396         return True;
397 }
398
399 /*******************************************************************
400  Ensure we can read/write to a given offset.
401  ********************************************************************/
402
403 char *prs_mem_get(prs_struct *ps, uint32 extra_size)
404 {
405         if(UNMARSHALLING(ps)) {
406                 /*
407                  * If reading, ensure that we can read the requested size item.
408                  */
409                 if (ps->data_offset + extra_size > ps->buffer_size) {
410                         DEBUG(0,("prs_mem_get: reading data of size %u would overrun buffer.\n",
411                                         (unsigned int)extra_size ));
412                         return NULL;
413                 }
414         } else {
415                 /*
416                  * Writing - grow the buffer if needed.
417                  */
418                 if(!prs_grow(ps, extra_size))
419                         return False;
420         }
421         return &ps->data_p[ps->data_offset];
422 }
423
424 /*******************************************************************
425  Change the struct type.
426  ********************************************************************/
427
428 void prs_switch_type(prs_struct *ps, BOOL io)
429 {
430         if ((ps->io ^ io) == True)
431                 ps->io=io;
432 }
433
434 /*******************************************************************
435  Force a prs_struct to be dynamic even when it's size is 0.
436  ********************************************************************/
437
438 void prs_force_dynamic(prs_struct *ps)
439 {
440         ps->is_dynamic=True;
441 }
442
443 /*******************************************************************
444  Stream a uint8.
445  ********************************************************************/
446
447 BOOL prs_uint8(char *name, prs_struct *ps, int depth, uint8 *data8)
448 {
449         char *q = prs_mem_get(ps, sizeof(uint8));
450         if (q == NULL)
451                 return False;
452
453         DBG_RW_CVAL(name, depth, ps->data_offset, ps->io, q, *data8)
454         ps->data_offset += sizeof(uint8);
455
456         return True;
457 }
458
459 /*******************************************************************
460  Stream a uint16.
461  ********************************************************************/
462
463 BOOL prs_uint16(char *name, prs_struct *ps, int depth, uint16 *data16)
464 {
465         char *q = prs_mem_get(ps, sizeof(uint16));
466         if (q == NULL)
467                 return False;
468
469         DBG_RW_SVAL(name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, *data16)
470         ps->data_offset += sizeof(uint16);
471
472         return True;
473 }
474
475 /*******************************************************************
476  Stream a uint32.
477  ********************************************************************/
478
479 BOOL prs_uint32(char *name, prs_struct *ps, int depth, uint32 *data32)
480 {
481         char *q = prs_mem_get(ps, sizeof(uint32));
482         if (q == NULL)
483                 return False;
484
485         DBG_RW_IVAL(name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, *data32)
486         ps->data_offset += sizeof(uint32);
487
488         return True;
489 }
490
491 /******************************************************************
492  Stream an array of uint8s. Length is number of uint8s.
493  ********************************************************************/
494
495 BOOL prs_uint8s(BOOL charmode, char *name, prs_struct *ps, int depth, uint8 *data8s, int len)
496 {
497         char *q = prs_mem_get(ps, len * sizeof(uint8));
498         if (q == NULL)
499                 return False;
500
501         DBG_RW_PCVAL(charmode, name, depth, ps->data_offset, ps->io, q, data8s, len)
502         ps->data_offset += (len * sizeof(uint8));
503
504         return True;
505 }
506
507 /******************************************************************
508  Stream an array of uint16s. Length is number of uint16s.
509  ********************************************************************/
510
511 BOOL prs_uint16s(BOOL charmode, char *name, prs_struct *ps, int depth, uint16 *data16s, int len)
512 {
513         char *q = prs_mem_get(ps, len * sizeof(uint16));
514         if (q == NULL)
515                 return False;
516
517         DBG_RW_PSVAL(charmode, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, data16s, len)
518         ps->data_offset += (len * sizeof(uint16));
519
520         return True;
521 }
522
523 /******************************************************************
524  Stream an array of uint32s. Length is number of uint32s.
525  ********************************************************************/
526
527 BOOL prs_uint32s(BOOL charmode, char *name, prs_struct *ps, int depth, uint32 *data32s, int len)
528 {
529         char *q = prs_mem_get(ps, len * sizeof(uint32));
530         if (q == NULL)
531                 return False;
532
533         DBG_RW_PIVAL(charmode, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, data32s, len)
534         ps->data_offset += (len * sizeof(uint32));
535
536         return True;
537 }
538
539 /******************************************************************
540  Stream a "not" unicode string, length/buffer specified separately,
541  in byte chars. String is in little-endian format.
542  ********************************************************************/
543
544 BOOL prs_buffer2(BOOL charmode, char *name, prs_struct *ps, int depth, BUFFER2 *str)
545 {
546         char *p = (char *)str->buffer;
547         char *q = prs_mem_get(ps, str->buf_len);
548         if (q == NULL)
549                 return False;
550
551         /* If we're using big-endian, reverse to get little-endian. */
552         if(ps->bigendian_data)
553                 DBG_RW_PSVAL(charmode, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, p, str->buf_len/2)
554         else
555                 DBG_RW_PCVAL(charmode, name, depth, ps->data_offset, ps->io, q, p, str->buf_len)
556         ps->data_offset += str->buf_len;
557
558         return True;
559 }
560
561 /******************************************************************
562  Stream a string, length/buffer specified separately,
563  in uint8 chars.
564  ********************************************************************/
565
566 BOOL prs_string2(BOOL charmode, char *name, prs_struct *ps, int depth, STRING2 *str)
567 {
568         char *q = prs_mem_get(ps, str->str_str_len * sizeof(uint8));
569         if (q == NULL)
570                 return False;
571
572         DBG_RW_PCVAL(charmode, name, depth, ps->data_offset, ps->io, q, str->buffer, str->str_max_len)
573         ps->data_offset += (str->str_str_len * sizeof(uint8));
574
575         return True;
576 }
577
578 /******************************************************************
579  Stream a unicode string, length/buffer specified separately,
580  in uint16 chars. We use DBG_RW_PCVAL, not DBG_RW_PSVAL here
581  as the unicode string is already in little-endian format.
582  ********************************************************************/
583
584 BOOL prs_unistr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNISTR2 *str)
585 {
586         char *p = (char *)str->buffer;
587         char *q = prs_mem_get(ps, str->uni_str_len * sizeof(uint16));
588         if (q == NULL)
589                 return False;
590
591         /* If we're using big-endian, reverse to get little-endian. */
592         if(ps->bigendian_data)
593                 DBG_RW_PSVAL(charmode, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, p, str->uni_str_len)
594         else
595                 DBG_RW_PCVAL(charmode, name, depth, ps->data_offset, ps->io, q, p, str->uni_str_len * 2)
596         ps->data_offset += (str->uni_str_len * sizeof(uint16));
597
598         return True;
599 }
600
601
602
603 /******************************************************************
604  Stream a unicode string, length/buffer specified separately,
605  in uint16 chars. We use DBG_RW_PCVAL, not DBG_RW_PSVAL here
606  as the unicode string is already in little-endian format.
607  ********************************************************************/
608
609 BOOL prs_unistr3(BOOL charmode, char *name, UNISTR3 *str, prs_struct *ps, int depth)
610 {
611         char *p = (char *)str->str.buffer;
612         char *q = prs_mem_get(ps, str->uni_str_len * sizeof(uint16));
613         if (q == NULL)
614                 return False;
615
616         /* If we're using big-endian, reverse to get little-endian. */
617         if(ps->bigendian_data)
618                 DBG_RW_PSVAL(charmode, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, p, str->uni_str_len)
619         else
620                 DBG_RW_PCVAL(charmode, name, depth, ps->data_offset, ps->io, q, p, str->uni_str_len * 2)
621         ps->data_offset += (str->uni_str_len * sizeof(uint16));
622
623         return True;
624 }
625
626 /*******************************************************************
627  Stream a unicode  null-terminated string. As the string is already
628  in little-endian format then do it as a stream of bytes.
629  ********************************************************************/
630
631 #ifndef RPCCLIENT_TEST
632 BOOL prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str)
633 {
634         int len = 0;
635         unsigned char *p = (unsigned char *)str->buffer;
636         uint8 *start;
637         char *q;
638         char zero=0;
639
640         for(len = 0; len < (sizeof(str->buffer) / sizeof(str->buffer[0])) &&
641                            str->buffer[len] != 0; len++)
642                 ;
643
644         q = prs_mem_get(ps, (len+1)*2);
645         if (q == NULL)
646                 return False;
647
648         start = (uint8*)q;
649
650         for(len = 0; len < (sizeof(str->buffer) / sizeof(str->buffer[0])) &&
651                            str->buffer[len] != 0; len++) {
652                 if(ps->bigendian_data) {
653                         RW_SVAL(ps->io, ps->bigendian_data, q, *p, 0);
654                         p += 2;
655                         q += 2;
656                 } else {
657                         RW_CVAL(ps->io, q, *p, 0);
658                         p++;
659                         q++;
660                         RW_CVAL(ps->io, q, *p, 0);
661                         p++;
662                         q++;
663                 }
664         }
665         
666         /*
667          * even if the string is 'empty' (only an \0 char)
668          * at this point the leading \0 hasn't been parsed.
669          * so parse it now
670          */
671
672         RW_CVAL(ps->io, q, zero, 0);
673         q++;
674         RW_CVAL(ps->io, q, zero, 0);
675         q++;
676
677         len++;
678                 
679         ps->data_offset += len*2;
680
681         dump_data(5+depth, (char *)start, len * 2);
682
683         return True;
684 }
685 #else
686 BOOL prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str)
687 {
688         int len = 0;
689         unsigned char *p = (unsigned char *)str->buffer;
690         uint8 *start;
691         char *q;
692         char zero=0;
693
694         if (MARSHALLING(ps)) {
695
696                 for(len = 0; len < (sizeof(str->buffer) / sizeof(str->buffer[0])) &&
697                                    str->buffer[len] != 0; len++)
698                         ;
699
700                 q = prs_mem_get(ps, (len+1)*2);
701                 if (q == NULL)
702                         return False;
703
704                 start = (uint8*)q;
705
706                 for(len = 0; len < (sizeof(str->buffer) / sizeof(str->buffer[0])) &&
707                                    str->buffer[len] != 0; len++) 
708                 {
709                         if(ps->bigendian_data) 
710                         {
711                                 RW_SVAL(ps->io, ps->bigendian_data, q, *p, 0);
712                                 p += 2;
713                                 q += 2;
714                         } 
715                         else 
716                         {
717                                 RW_CVAL(ps->io, q, *p, 0);
718                                 p++;
719                                 q++;
720                                 RW_CVAL(ps->io, q, *p, 0);
721                                 p++;
722                                 q++;
723                         }
724                 }
725
726                 /*
727                  * even if the string is 'empty' (only an \0 char)
728                  * at this point the leading \0 hasn't been parsed.
729                  * so parse it now
730                  */
731
732                 RW_CVAL(ps->io, q, zero, 0);
733                 q++;
734                 RW_CVAL(ps->io, q, zero, 0);
735                 q++;
736
737                 len++;
738
739                 dump_data(5+depth, (char *)start, len * 2);
740         }
741         else { /* unmarshalling */
742         
743                 len = -1;
744                 q = prs_data_p(ps) + prs_offset(ps);
745
746                 do 
747                 {
748                         len++;
749
750                         if(ps->bigendian_data) 
751                         {
752                                 RW_SVAL(ps->io, ps->bigendian_data, q, *p, 0);
753                                 p += 2;
754                                 q += 2;
755                         } else {
756                                 RW_CVAL(ps->io, q, *p, 0);
757                                 p++;
758                                 q++;
759                                 RW_CVAL(ps->io, q, *p, 0);
760                                 p++;
761                                 q++;
762                         }
763                 } while (len < (sizeof(str->buffer) / sizeof(str->buffer[0])) &&
764                                    str->buffer[len] != 0);
765         }
766
767         ps->data_offset += len*2;
768         
769         return True;
770 }
771
772 #endif  /* RPCCLIENT_TEST */
773
774
775 /*******************************************************************
776  Stream a null-terminated string.  len is strlen, and therefore does
777  not include the null-termination character.
778  ********************************************************************/
779
780 BOOL prs_string(char *name, prs_struct *ps, int depth, char *str, int len, int max_buf_size)
781 {
782         char *q;
783         uint8 *start;
784         int i;
785
786         len = MIN(len, (max_buf_size-1));
787
788         q = prs_mem_get(ps, len+1);
789         if (q == NULL)
790                 return False;
791
792         start = (uint8*)q;
793
794         for(i = 0; i < len; i++) {
795                 RW_CVAL(ps->io, q, str[i],0);
796                 q++;
797         }
798
799         /* The terminating null. */
800         str[i] = '\0';
801
802         if (MARSHALLING(ps)) {
803                 RW_CVAL(ps->io, q, str[i], 0);
804         }
805
806         ps->data_offset += len+1;
807
808         dump_data(5+depth, (char *)start, len);
809
810         return True;
811 }
812
813 /*******************************************************************
814  prs_uint16 wrapper. Call this and it sets up a pointer to where the
815  uint16 should be stored, or gets the size if reading.
816  ********************************************************************/
817
818 BOOL prs_uint16_pre(char *name, prs_struct *ps, int depth, uint16 *data16, uint32 *offset)
819 {
820         (*offset) = ps->data_offset;
821         if (UNMARSHALLING(ps)) {
822                 /* reading. */
823                 return prs_uint16(name, ps, depth, data16);
824         } else {
825                 char *q = prs_mem_get(ps, sizeof(uint16));
826                 if(q ==NULL)
827                         return False;
828                 ps->data_offset += sizeof(uint16);
829         }
830         return True;
831 }
832
833 /*******************************************************************
834  prs_uint16 wrapper.  call this and it retrospectively stores the size.
835  does nothing on reading, as that is already handled by ...._pre()
836  ********************************************************************/
837
838 BOOL prs_uint16_post(char *name, prs_struct *ps, int depth, uint16 *data16,
839                                 uint32 ptr_uint16, uint32 start_offset)
840 {
841         if (MARSHALLING(ps)) {
842                 /* 
843                  * Writing - temporarily move the offset pointer.
844                  */
845                 uint16 data_size = ps->data_offset - start_offset;
846                 uint32 old_offset = ps->data_offset;
847
848                 ps->data_offset = ptr_uint16;
849                 if(!prs_uint16(name, ps, depth, &data_size)) {
850                         ps->data_offset = old_offset;
851                         return False;
852                 }
853                 ps->data_offset = old_offset;
854         } else {
855                 ps->data_offset = start_offset + (uint32)(*data16);
856         }
857         return True;
858 }
859
860 /*******************************************************************
861  prs_uint32 wrapper. Call this and it sets up a pointer to where the
862  uint32 should be stored, or gets the size if reading.
863  ********************************************************************/
864
865 BOOL prs_uint32_pre(char *name, prs_struct *ps, int depth, uint32 *data32, uint32 *offset)
866 {
867         (*offset) = ps->data_offset;
868         if (UNMARSHALLING(ps)) {
869                 /* reading. */
870                 return prs_uint32(name, ps, depth, data32);
871         } else {
872                 ps->data_offset += sizeof(uint32);
873         }
874         return True;
875 }
876
877 /*******************************************************************
878  prs_uint32 wrapper.  call this and it retrospectively stores the size.
879  does nothing on reading, as that is already handled by ...._pre()
880  ********************************************************************/
881
882 BOOL prs_uint32_post(char *name, prs_struct *ps, int depth, uint32 *data32,
883                                 uint32 ptr_uint32, uint32 data_size)
884 {
885         if (MARSHALLING(ps)) {
886                 /* 
887                  * Writing - temporarily move the offset pointer.
888                  */
889                 uint32 old_offset = ps->data_offset;
890                 ps->data_offset = ptr_uint32;
891                 if(!prs_uint32(name, ps, depth, &data_size)) {
892                         ps->data_offset = old_offset;
893                         return False;
894                 }
895                 ps->data_offset = old_offset;
896         }
897         return True;
898 }
899
900 /*******************************************************************
901  frees a memory buffer.
902  ********************************************************************/
903 void prs_free_data(prs_struct *buf)
904 {
905         if (buf == NULL)
906                 return;
907
908         if (buf->data_p != NULL)
909         {
910                 free(buf->data_p);
911                 buf->data_p = NULL;
912         }
913         buf->buffer_size = 0;
914 }
915
916 /*******************************************************************
917  reallocate a memory buffer
918 ********************************************************************/
919 BOOL prs_realloc_data(prs_struct *buf, size_t new_size)
920 {
921         char *new_data;
922
923         /* prs_sma_init();  JERRY */
924
925         prs_debug(buf, 200, "prs_realloc_data - before", "prs_realloc_data");
926
927         SMB_ASSERT(((ssize_t) new_size) >= 0);
928
929         if (new_size == 0)
930         {
931                 prs_free_data(buf);
932                 return True;
933         }
934
935         /* new_data = sma_realloc(prs_sma_region, buf->data_p, new_size); */
936         new_data = realloc(buf->data_p, new_size);
937
938         if (new_data != NULL)
939         {
940                 if (new_size > buf->buffer_size)
941                 {
942                         memset(&new_data[buf->buffer_size], 0,
943                                new_size - buf->buffer_size);
944                 }
945                 buf->data_p = new_data;
946                 buf->buffer_size = new_size;
947         }
948         else if (buf->buffer_size >= new_size)
949         {
950                 DEBUG(3, ("prs_realloc_data: warning - "
951                           "could not realloc to %d\n", new_size));
952         }
953         else
954         {
955                 DEBUG(3, ("prs_realloc_data: error - "
956                           "could not realloc to %d\n", new_size));
957
958                 prs_free_data(buf);
959                 return False;
960         }
961
962         prs_debug(buf, 200, "prs_realloc_data - after", "prs_realloc_data");
963         return True;
964 }
965
966 /*******************************************************************
967  return the memory location specified by offset; may return NULL.
968  ********************************************************************/
969 char *prs_data(const prs_struct *buf, uint32 offset)
970 {
971
972         /* do we have something to look at? */
973         if (buf == NULL)
974                 return NULL;
975
976         /* check to make sure the offset is within range */
977         if ((offset < 0) || (offset >= buf->buffer_size))
978                 return NULL;
979
980         /* locate the memory address */
981         if (buf->data_p != NULL)
982         {
983                 return &(buf->data_p[offset]);
984         }
985
986         /* default return */
987         return NULL;
988 }
989
990
991
992
993 /* useful function to store a structure in rpc wire format */
994 int tdb_prs_store(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps)
995 {
996     TDB_DATA kbuf, dbuf;
997     kbuf.dptr = keystr;
998     kbuf.dsize = strlen(keystr)+1;
999     dbuf.dptr = prs_data_p(ps);
1000     dbuf.dsize = prs_offset(ps);
1001     return tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1002 }
1003
1004 /* useful function to fetch a structure into rpc wire format */
1005 int tdb_prs_fetch(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps)
1006 {
1007     TDB_DATA kbuf, dbuf;
1008     kbuf.dptr = keystr;
1009     kbuf.dsize = strlen(keystr)+1;
1010
1011     dbuf = tdb_fetch(tdb, kbuf);
1012     if (!dbuf.dptr) return -1;
1013
1014     ZERO_STRUCTP(ps);
1015     prs_init(ps, 0, 4, UNMARSHALL);
1016     prs_give_memory(ps, dbuf.dptr, dbuf.dsize, True);
1017
1018     return 0;
1019