security descriptors and registry.
[samba.git] / source / 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    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 extern int DEBUGLEVEL;
24
25 #include "includes.h"
26
27
28 /*******************************************************************
29  debug output for parsing info.
30
31  XXXX side-effect of this function is to increase the debug depth XXXX
32
33  ********************************************************************/
34 void prs_debug(prs_struct *ps, int depth, char *desc, char *fn_name)
35 {
36         DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->offset, fn_name, desc));
37 }
38
39 /*******************************************************************
40  initialise a parse structure
41  ********************************************************************/
42 void prs_init(prs_struct *ps, uint32 size,
43                                 uint8 align, uint32 margin,
44                                 BOOL io)
45 {
46         ps->io = io;
47         ps->align = align;
48         ps->offset = 0;
49
50         ps->data = NULL;
51         mem_buf_init(&(ps->data), margin);
52
53         if (size != 0)
54         {
55                 mem_alloc_data(ps->data, size);
56                 ps->data->offset.start = 0;
57                 ps->data->offset.end   = 0xffffffff;
58         }
59 }
60
61 /*******************************************************************
62  initialise a parse structure
63  ********************************************************************/
64 void prs_mem_free(prs_struct *ps)
65 {
66         mem_buf_free(&(ps->data));
67 }
68
69 /*******************************************************************
70  link one parsing structure to another
71  ********************************************************************/
72 void prs_link(prs_struct *prev, prs_struct *ps, prs_struct *next)
73 {
74         ps->data->offset.start = prev != NULL ? prev->data->offset.end : 0;
75         ps->data->offset.end   = ps->data->offset.start + ps->offset;
76         ps->data->next         = next != NULL ? next->data : NULL;
77 }
78
79 /*******************************************************************
80  align a pointer to a multiple of align_offset bytes.  looks like it
81  will work for offsets of 0, 2 and 4...
82  ********************************************************************/
83 void prs_align(prs_struct *ps)
84 {
85         int mod = ps->offset & (ps->align-1);
86         if (ps->align != 0 && mod != 0)
87         {
88                 ps->offset += ps->align - mod;
89         }
90 }
91
92 /*******************************************************************
93  attempt, if appropriate, to grow a data buffer.
94
95  depends on the data stream mode (io)
96  ********************************************************************/
97 BOOL prs_grow(prs_struct *ps)
98 {
99         return mem_grow_data(&(ps->data), ps->io, ps->offset, False);
100 }
101
102
103 /*******************************************************************
104  stream a uint8
105  ********************************************************************/
106 BOOL prs_uint8(char *name, prs_struct *ps, int depth, uint8 *data8)
107 {
108         char *q = mem_data(&(ps->data), ps->offset);
109         if (q == NULL) return False;
110
111         DBG_RW_CVAL(name, depth, ps->offset, ps->io, q, *data8)
112         ps->offset += 1;
113
114         return True;
115 }
116
117 /*******************************************************************
118  stream a uint16
119  ********************************************************************/
120 BOOL prs_uint16(char *name, prs_struct *ps, int depth, uint16 *data16)
121 {
122         char *q = mem_data(&(ps->data), ps->offset);
123         if (q == NULL) return False;
124
125         DBG_RW_SVAL(name, depth, ps->offset, ps->io, q, *data16)
126         ps->offset += 2;
127
128         return True;
129 }
130
131 /*******************************************************************
132  stream a uint32
133  ********************************************************************/
134 BOOL prs_uint32(char *name, prs_struct *ps, int depth, uint32 *data32)
135 {
136         char *q = mem_data(&(ps->data), ps->offset);
137         if (q == NULL) return False;
138
139         DBG_RW_IVAL(name, depth, ps->offset, ps->io, q, *data32)
140         ps->offset += 4;
141
142         return True;
143 }
144
145
146 /******************************************************************
147  stream an array of uint8s.  length is number of uint8s
148  ********************************************************************/
149 BOOL prs_uint8s(BOOL charmode, char *name, prs_struct *ps, int depth, uint8 *data8s, int len)
150 {
151         char *q = mem_data(&(ps->data), ps->offset);
152         if (q == NULL) return False;
153
154         DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, data8s, len)
155         ps->offset += len;
156
157         return True;
158 }
159
160 /******************************************************************
161  stream an array of uint32s.  length is number of uint32s
162  ********************************************************************/
163 BOOL prs_uint32s(BOOL charmode, char *name, prs_struct *ps, int depth, uint32 *data32s, int len)
164 {
165         char *q = mem_data(&(ps->data), ps->offset);
166         if (q == NULL) return False;
167
168         DBG_RW_PIVAL(charmode, name, depth, ps->offset, ps->io, q, data32s, len)
169         ps->offset += len * sizeof(uint32);
170
171         return True;
172 }
173
174 /******************************************************************
175  stream a "not" unicode string, length/buffer specified separately,
176  in byte chars
177  ********************************************************************/
178 BOOL prs_buffer2(BOOL charmode, char *name, prs_struct *ps, int depth, BUFFER2 *str)
179 {
180         char *q = mem_data(&(ps->data), ps->offset);
181         if (q == NULL) return False;
182
183         DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->buf_len/2)
184         ps->offset += str->buf_len;
185
186         return True;
187 }
188
189 /******************************************************************
190  stream a string, length/buffer specified separately,
191  in uint8 chars.
192  ********************************************************************/
193 BOOL prs_string2(BOOL charmode, char *name, prs_struct *ps, int depth, STRING2 *str)
194 {
195         char *q = mem_data(&(ps->data), ps->offset);
196         if (q == NULL) return False;
197
198         DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->str_max_len)
199         ps->offset += str->str_str_len * sizeof(uint8);
200
201         return True;
202 }
203
204 /******************************************************************
205  stream a unicode string, length/buffer specified separately,
206  in uint16 chars.
207  ********************************************************************/
208 BOOL prs_unistr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNISTR2 *str)
209 {
210         char *q = mem_data(&(ps->data), ps->offset);
211         if (q == NULL) return False;
212
213         DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->uni_str_len)
214         ps->offset += str->uni_str_len * sizeof(uint16);
215
216         return True;
217 }
218
219 /******************************************************************
220  stream a unicode string, length/buffer specified separately,
221  in uint16 chars.
222  ********************************************************************/
223 BOOL prs_unistr3(BOOL charmode, char *name, UNISTR3 *str, prs_struct *ps, int depth)
224 {
225         char *q = mem_data(&(ps->data), ps->offset);
226         if (q == NULL) return False;
227
228         DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, str->str.buffer, str->uni_str_len)
229         ps->offset += str->uni_str_len * sizeof(uint16);
230
231         return True;
232 }
233
234 /*******************************************************************
235  stream a unicode  null-terminated string
236  ********************************************************************/
237 BOOL prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str)
238 {
239         char *q = mem_data(&(ps->data), ps->offset);
240         int i = 0;
241         uint8 *start = (uint8*)q;
242
243         if (q == NULL) return False;
244
245         do 
246         {
247                 RW_SVAL(ps->io, q, str->buffer[i],0);
248                 q += 2;
249                 i++;
250
251         } while ((i < sizeof(str->buffer) / sizeof(str->buffer[0])) &&
252                      (str->buffer[i] != 0));
253
254         ps->offset += i*2;
255
256         dump_data(5+depth, (char *)start, i * 2);
257
258         return True;
259 }
260
261 /*******************************************************************
262  stream a null-terminated string.  len is strlen, and therefore does
263  not include the null-termination character.
264
265  len == 0 indicates variable length string
266  (up to max size of pstring - 1024 chars).
267
268  ********************************************************************/
269 BOOL prs_string(char *name, prs_struct *ps, int depth, char *str, uint16 len, uint16 max_buf_size)
270 {
271         char *q = mem_data(&(ps->data), ps->offset);
272         uint8 *start = (uint8*)q;
273         int i = -1; /* start off at zero after 1st i++ */
274
275         if (q == NULL) return False;
276
277         do
278         {
279                 i++;
280
281                 if (i < len || len == 0)
282                 {
283                         RW_CVAL(ps->io, q, str[i],0);
284                 }
285                 else
286                 {
287                         uint8 dummy = 0;
288                         RW_CVAL(ps->io, q, dummy,0);
289                 }
290
291                 q++;
292
293         } while (i < max_buf_size && (len == 0 ? str[i] != 0 : i < len) );
294
295         ps->offset += i+1;
296
297         dump_data(5+depth, (char *)start, i);
298
299         return True;
300 }
301
302 /*******************************************************************
303  prs_uint16 wrapper.  call this and it sets up a pointer to where the
304  uint16 should be stored, or gets the size if reading
305  ********************************************************************/
306 BOOL prs_uint16_pre(char *name, prs_struct *ps, int depth, uint16 *data16, uint32 *offset)
307 {
308         (*offset) = ps->offset;
309         if (ps->io)
310         {
311                 /* reading. */
312                 return prs_uint16(name, ps, depth, data16);
313         }
314         else
315         {
316                 ps->offset += sizeof(uint16);
317         }
318         return True;
319 }
320
321 /*******************************************************************
322  prs_uint16 wrapper.  call this and it retrospectively stores the size.
323  does nothing on reading, as that is already handled by ...._pre()
324  ********************************************************************/
325 BOOL prs_uint16_post(char *name, prs_struct *ps, int depth, uint16 *data16,
326                                 uint32 ptr_uint16, uint32 start_offset)
327 {
328         if (!ps->io)
329         {
330                 /* storing: go back and do a retrospective job.  i hate this */
331                 uint16 data_size = ps->offset - start_offset;
332                 uint32 old_offset = ps->offset;
333
334                 ps->offset = ptr_uint16;
335                 prs_uint16(name, ps, depth, &data_size);
336                 ps->offset = old_offset;
337         }
338         else
339         {
340                 ps->offset = start_offset + (*data16);
341         }
342         return True;
343 }
344
345 /*******************************************************************
346  prs_uint32 wrapper.  call this and it sets up a pointer to where the
347  uint32 should be stored, or gets the size if reading
348  ********************************************************************/
349 BOOL prs_uint32_pre(char *name, prs_struct *ps, int depth, uint32 *data32, uint32 *offset)
350 {
351         (*offset) = ps->offset;
352         if (ps->io)
353         {
354                 /* reading. */
355                 return prs_uint32(name, ps, depth, data32);
356         }
357         else
358         {
359                 ps->offset += sizeof(uint32);
360         }
361         return True;
362 }
363
364 /*******************************************************************
365  prs_uint32 wrapper.  call this and it retrospectively stores the size.
366  does nothing on reading, as that is already handled by ...._pre()
367  ********************************************************************/
368 BOOL prs_uint32_post(char *name, prs_struct *ps, int depth, uint32 *data32,
369                                 uint32 ptr_uint32, uint32 start_offset)
370 {
371         if (!ps->io)
372         {
373                 /* storing: go back and do a retrospective job.  i hate this */
374                 uint32 data_size = ps->offset - start_offset;
375                 uint32 old_offset = ps->offset;
376
377                 ps->offset = ptr_uint32;
378                 prs_uint32(name, ps, depth, &data_size);
379                 ps->offset = old_offset;
380         }
381         else
382         {
383                 ps->offset = start_offset + (*data32);
384         }
385         return True;
386 }
387