r6369: update release notes
[Samba.git] / source / rpc_parse / parse_buffer.c
bloba48d5cfa982b3a6718daa96341ea7d582013ea8a
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 *
5 * Copyright (C) Andrew Tridgell 1992-2000,
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7 * Copyright (C) Jean François Micouleau 1998-2000,
8 * Copyright (C) Gerald Carter 2000-2005,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_RPC_PARSE
31 /**********************************************************************
32 Initialize a new spoolss buff for use by a client rpc
33 **********************************************************************/
34 void rpcbuf_init(RPC_BUFFER *buffer, uint32 size, TALLOC_CTX *ctx)
36 buffer->size = size;
37 buffer->string_at_end = size;
38 prs_init(&buffer->prs, size, ctx, MARSHALL);
39 buffer->struct_start = prs_offset(&buffer->prs);
42 /*******************************************************************
43 Read/write a RPC_BUFFER struct.
44 ********************************************************************/
46 BOOL prs_rpcbuffer(const char *desc, prs_struct *ps, int depth, RPC_BUFFER *buffer)
48 prs_debug(ps, depth, desc, "prs_rpcbuffer");
49 depth++;
51 /* reading */
52 if (UNMARSHALLING(ps)) {
53 buffer->size=0;
54 buffer->string_at_end=0;
56 if (!prs_uint32("size", ps, depth, &buffer->size))
57 return False;
60 * JRA. I'm not sure if the data in here is in big-endian format if
61 * the client is big-endian. Leave as default (little endian) for now.
64 if (!prs_init(&buffer->prs, buffer->size, prs_get_mem_context(ps), UNMARSHALL))
65 return False;
67 if (!prs_append_some_prs_data(&buffer->prs, ps, prs_offset(ps), buffer->size))
68 return False;
70 if (!prs_set_offset(&buffer->prs, 0))
71 return False;
73 if (!prs_set_offset(ps, buffer->size+prs_offset(ps)))
74 return False;
76 buffer->string_at_end=buffer->size;
78 return True;
80 else {
81 BOOL ret = False;
83 if (!prs_uint32("size", ps, depth, &buffer->size))
84 goto out;
86 if (!prs_append_some_prs_data(ps, &buffer->prs, 0, buffer->size))
87 goto out;
89 ret = True;
90 out:
92 /* We have finished with the data in buffer->prs - free it. */
93 prs_mem_free(&buffer->prs);
95 return ret;
99 /*******************************************************************
100 Read/write an RPC_BUFFER* struct.(allocate memory if unmarshalling)
101 ********************************************************************/
103 BOOL prs_rpcbuffer_p(const char *desc, prs_struct *ps, int depth, RPC_BUFFER **buffer)
105 uint32 data_p;
107 /* caputure the pointer value to stream */
109 data_p = (uint32) *buffer;
111 if ( !prs_uint32("ptr", ps, depth, &data_p ))
112 return False;
114 /* we're done if there is no data */
116 if ( !data_p )
117 return True;
119 if ( UNMARSHALLING(ps) ) {
120 if ( !(*buffer = PRS_ALLOC_MEM(ps, RPC_BUFFER, 1)) )
121 return False;
124 return prs_rpcbuffer( desc, ps, depth, *buffer);
127 /****************************************************************************
128 Allocate more memory for a RPC_BUFFER.
129 ****************************************************************************/
131 BOOL rpcbuf_alloc_size(RPC_BUFFER *buffer, uint32 buffer_size)
133 prs_struct *ps;
134 uint32 extra_space;
135 uint32 old_offset;
137 /* if we don't need anything. don't do anything */
139 if ( buffer_size == 0x0 )
140 return True;
142 ps= &buffer->prs;
144 /* damn, I'm doing the reverse operation of prs_grow() :) */
145 if (buffer_size < prs_data_size(ps))
146 extra_space=0;
147 else
148 extra_space = buffer_size - prs_data_size(ps);
151 * save the offset and move to the end of the buffer
152 * prs_grow() checks the extra_space against the offset
154 old_offset=prs_offset(ps);
155 prs_set_offset(ps, prs_data_size(ps));
157 if (!prs_grow(ps, extra_space))
158 return False;
160 prs_set_offset(ps, old_offset);
162 buffer->string_at_end=prs_data_size(ps);
164 return True;
167 /*******************************************************************
168 move a BUFFER from the query to the reply.
169 As the data pointers in RPC_BUFFER are malloc'ed, not talloc'ed,
170 this is ok. This is an OPTIMIZATION and is not strictly neccessary.
171 Clears the memory to zero also.
172 ********************************************************************/
174 void rpcbuf_move(RPC_BUFFER *src, RPC_BUFFER **dest)
176 SMB_ASSERT( src != NULL );
178 prs_switch_type(&src->prs, MARSHALL);
179 if(!prs_set_offset(&src->prs, 0))
180 return;
181 prs_force_dynamic(&src->prs);
182 prs_mem_clear(&src->prs);
183 *dest=src;
186 /*******************************************************************
187 Get the size of a BUFFER struct.
188 ********************************************************************/
190 uint32 rpcbuf_get_size(RPC_BUFFER *buffer)
192 return (buffer->size);
196 /*******************************************************************
197 * write a UNICODE string and its relative pointer.
198 * used by all the RPC structs passing a buffer
200 * As I'm a nice guy, I'm forcing myself to explain this code.
201 * MS did a good job in the overall spoolss code except in some
202 * functions where they are passing the API buffer directly in the
203 * RPC request/reply. That's to maintain compatiility at the API level.
204 * They could have done it the good way the first time.
206 * So what happen is: the strings are written at the buffer's end,
207 * in the reverse order of the original structure. Some pointers to
208 * the strings are also in the buffer. Those are relative to the
209 * buffer's start.
211 * If you don't understand or want to change that function,
212 * first get in touch with me: jfm@samba.org
214 ********************************************************************/
216 BOOL smb_io_relstr(const char *desc, RPC_BUFFER *buffer, int depth, UNISTR *string)
218 prs_struct *ps=&buffer->prs;
220 if (MARSHALLING(ps)) {
221 uint32 struct_offset = prs_offset(ps);
222 uint32 relative_offset;
224 buffer->string_at_end -= (size_of_relative_string(string) - 4);
225 if(!prs_set_offset(ps, buffer->string_at_end))
226 return False;
227 #if 0 /* JERRY */
229 * Win2k does not align strings in a buffer
230 * Tested against WinNT 4.0 SP 6a & 2k SP2 --jerry
232 if (!prs_align(ps))
233 return False;
234 #endif
235 buffer->string_at_end = prs_offset(ps);
237 /* write the string */
238 if (!smb_io_unistr(desc, string, ps, depth))
239 return False;
241 if(!prs_set_offset(ps, struct_offset))
242 return False;
244 relative_offset=buffer->string_at_end - buffer->struct_start;
245 /* write its offset */
246 if (!prs_uint32("offset", ps, depth, &relative_offset))
247 return False;
249 else {
250 uint32 old_offset;
252 /* read the offset */
253 if (!prs_uint32("offset", ps, depth, &(buffer->string_at_end)))
254 return False;
256 if (buffer->string_at_end == 0)
257 return True;
259 old_offset = prs_offset(ps);
260 if(!prs_set_offset(ps, buffer->string_at_end+buffer->struct_start))
261 return False;
263 /* read the string */
264 if (!smb_io_unistr(desc, string, ps, depth))
265 return False;
267 if(!prs_set_offset(ps, old_offset))
268 return False;
270 return True;
273 /*******************************************************************
274 * write a array of UNICODE strings and its relative pointer.
275 * used by 2 RPC structs
276 ********************************************************************/
278 BOOL smb_io_relarraystr(const char *desc, RPC_BUFFER *buffer, int depth, uint16 **string)
280 UNISTR chaine;
282 prs_struct *ps=&buffer->prs;
284 if (MARSHALLING(ps)) {
285 uint32 struct_offset = prs_offset(ps);
286 uint32 relative_offset;
287 uint16 *p;
288 uint16 *q;
289 uint16 zero=0;
290 p=*string;
291 q=*string;
293 /* first write the last 0 */
294 buffer->string_at_end -= 2;
295 if(!prs_set_offset(ps, buffer->string_at_end))
296 return False;
298 if(!prs_uint16("leading zero", ps, depth, &zero))
299 return False;
301 while (p && (*p!=0)) {
302 while (*q!=0)
303 q++;
305 /* Yes this should be malloc not talloc. Don't change. */
307 chaine.buffer = SMB_MALLOC((q-p+1)*sizeof(uint16));
308 if (chaine.buffer == NULL)
309 return False;
311 memcpy(chaine.buffer, p, (q-p+1)*sizeof(uint16));
313 buffer->string_at_end -= (q-p+1)*sizeof(uint16);
315 if(!prs_set_offset(ps, buffer->string_at_end)) {
316 SAFE_FREE(chaine.buffer);
317 return False;
320 /* write the string */
321 if (!smb_io_unistr(desc, &chaine, ps, depth)) {
322 SAFE_FREE(chaine.buffer);
323 return False;
325 q++;
326 p=q;
328 SAFE_FREE(chaine.buffer);
331 if(!prs_set_offset(ps, struct_offset))
332 return False;
334 relative_offset=buffer->string_at_end - buffer->struct_start;
335 /* write its offset */
336 if (!prs_uint32("offset", ps, depth, &relative_offset))
337 return False;
339 } else {
341 /* UNMARSHALLING */
343 uint32 old_offset;
344 uint16 *chaine2=NULL;
345 int l_chaine=0;
346 int l_chaine2=0;
347 size_t realloc_size = 0;
349 *string=NULL;
351 /* read the offset */
352 if (!prs_uint32("offset", ps, depth, &buffer->string_at_end))
353 return False;
355 old_offset = prs_offset(ps);
356 if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start))
357 return False;
359 do {
360 if (!smb_io_unistr(desc, &chaine, ps, depth))
361 return False;
363 l_chaine=str_len_uni(&chaine);
365 /* we're going to add two more bytes here in case this
366 is the last string in the array and we need to add
367 an extra NULL for termination */
368 if (l_chaine > 0)
370 uint16 *tc2;
372 realloc_size = (l_chaine2+l_chaine+2)*sizeof(uint16);
374 /* Yes this should be realloc - it's freed below. JRA */
376 if((tc2=(uint16 *)SMB_REALLOC(chaine2, realloc_size)) == NULL) {
377 SAFE_FREE(chaine2);
378 return False;
380 else chaine2 = tc2;
381 memcpy(chaine2+l_chaine2, chaine.buffer, (l_chaine+1)*sizeof(uint16));
382 l_chaine2+=l_chaine+1;
385 } while(l_chaine!=0);
387 /* the end should be bould NULL terminated so add
388 the second one here */
389 if (chaine2)
391 chaine2[l_chaine2] = '\0';
392 *string=(uint16 *)TALLOC_MEMDUP(prs_get_mem_context(ps),chaine2,realloc_size);
393 SAFE_FREE(chaine2);
396 if(!prs_set_offset(ps, old_offset))
397 return False;
399 return True;
402 /*******************************************************************
403 Parse a DEVMODE structure and its relative pointer.
404 ********************************************************************/
406 BOOL smb_io_relsecdesc(const char *desc, RPC_BUFFER *buffer, int depth, SEC_DESC **secdesc)
408 prs_struct *ps= &buffer->prs;
410 prs_debug(ps, depth, desc, "smb_io_relsecdesc");
411 depth++;
413 if (MARSHALLING(ps)) {
414 uint32 struct_offset = prs_offset(ps);
415 uint32 relative_offset;
417 if (! *secdesc) {
418 relative_offset = 0;
419 if (!prs_uint32("offset", ps, depth, &relative_offset))
420 return False;
421 return True;
424 if (*secdesc != NULL) {
425 buffer->string_at_end -= sec_desc_size(*secdesc);
427 if(!prs_set_offset(ps, buffer->string_at_end))
428 return False;
429 /* write the secdesc */
430 if (!sec_io_desc(desc, secdesc, ps, depth))
431 return False;
433 if(!prs_set_offset(ps, struct_offset))
434 return False;
437 relative_offset=buffer->string_at_end - buffer->struct_start;
438 /* write its offset */
440 if (!prs_uint32("offset", ps, depth, &relative_offset))
441 return False;
442 } else {
443 uint32 old_offset;
445 /* read the offset */
446 if (!prs_uint32("offset", ps, depth, &buffer->string_at_end))
447 return False;
449 old_offset = prs_offset(ps);
450 if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start))
451 return False;
453 /* read the sd */
454 if (!sec_io_desc(desc, secdesc, ps, depth))
455 return False;
457 if(!prs_set_offset(ps, old_offset))
458 return False;
460 return True;
465 /*******************************************************************
466 * return the length of a UNICODE string in number of char, includes:
467 * - the leading zero
468 * - the relative pointer size
469 ********************************************************************/
471 uint32 size_of_relative_string(UNISTR *string)
473 uint32 size=0;
475 size=str_len_uni(string); /* the string length */
476 size=size+1; /* add the trailing zero */
477 size=size*2; /* convert in char */
478 size=size+4; /* add the size of the ptr */
480 #if 0 /* JERRY */
482 * Do not include alignment as Win2k does not align relative
483 * strings within a buffer --jerry
485 /* Ensure size is 4 byte multiple (prs_align is being called...). */
486 /* size += ((4 - (size & 3)) & 3); */
487 #endif
489 return size;