2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
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.
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)
37 buffer->ptr = (size != 0);
40 buffer->string_at_end = size;
41 prs_init(&buffer->prs, size, ctx, MARSHALL);
42 buffer->struct_start = prs_offset(&buffer->prs);
45 /*******************************************************************
46 Read/write a RPC_BUFFER struct.
47 ********************************************************************/
49 BOOL prs_rpcbuffer(const char *desc, prs_struct *ps, int depth, RPC_BUFFER *buffer)
51 prs_debug(ps, depth, desc, "prs_rpcbuffer");
55 if (UNMARSHALLING(ps)) {
57 buffer->string_at_end=0;
62 * JRA. I'm not sure if the data in here is in big-endian format if
63 * the client is big-endian. Leave as default (little endian) for now.
66 if (!prs_init(&buffer->prs, 0, prs_get_mem_context(ps), UNMARSHALL))
72 if (!prs_uint32("size", ps, depth, &buffer->size))
76 * JRA. I'm not sure if the data in here is in big-endian format if
77 * the client is big-endian. Leave as default (little endian) for now.
80 if (!prs_init(&buffer->prs, buffer->size, prs_get_mem_context(ps), UNMARSHALL))
83 if (!prs_append_some_prs_data(&buffer->prs, ps, prs_offset(ps), buffer->size))
86 if (!prs_set_offset(&buffer->prs, 0))
89 if (!prs_set_offset(ps, buffer->size+prs_offset(ps)))
92 buffer->string_at_end=buffer->size;
101 if (buffer->ptr==0) {
102 /* We have finished with the data in buffer->prs - free it. */
103 prs_mem_free(&buffer->prs);
108 if (!prs_uint32("size", ps, depth, &buffer->size))
111 if (!prs_append_some_prs_data(ps, &buffer->prs, 0, buffer->size))
117 /* We have finished with the data in buffer->prs - free it. */
118 prs_mem_free(&buffer->prs);
124 /*******************************************************************
125 Read/write an RPC_BUFFER* struct.(allocate memory if unmarshalling)
126 ********************************************************************/
128 BOOL prs_rpcbuffer_p(const char *desc, prs_struct *ps, int depth, RPC_BUFFER **buffer)
132 /* caputure the pointer value to stream */
134 data_p = (uint32) *buffer;
136 if ( !prs_uint32("ptr", ps, depth, &data_p ))
139 /* we're done if there is no data */
144 if ( UNMARSHALLING(ps) ) {
145 if ( !(*buffer = PRS_ALLOC_MEM(ps, RPC_BUFFER, 1)) )
149 return prs_rpcbuffer( desc, ps, depth, *buffer);
152 /****************************************************************************
153 Allocate more memory for a RPC_BUFFER.
154 ****************************************************************************/
156 BOOL rpcbuf_alloc_size(RPC_BUFFER *buffer, uint32 buffer_size)
164 /* damn, I'm doing the reverse operation of prs_grow() :) */
165 if (buffer_size < prs_data_size(ps))
168 extra_space = buffer_size - prs_data_size(ps);
171 * save the offset and move to the end of the buffer
172 * prs_grow() checks the extra_space against the offset
174 old_offset=prs_offset(ps);
175 prs_set_offset(ps, prs_data_size(ps));
177 if (!prs_grow(ps, extra_space))
180 prs_set_offset(ps, old_offset);
182 buffer->string_at_end=prs_data_size(ps);
187 /*******************************************************************
188 move a BUFFER from the query to the reply.
189 As the data pointers in RPC_BUFFER are malloc'ed, not talloc'ed,
190 this is ok. This is an OPTIMIZATION and is not strictly neccessary.
191 Clears the memory to zero also.
192 ********************************************************************/
194 void rpcbuf_move(RPC_BUFFER *src, RPC_BUFFER **dest)
199 prs_switch_type(&src->prs, MARSHALL);
200 if(!prs_set_offset(&src->prs, 0))
202 prs_force_dynamic(&src->prs);
203 prs_mem_clear(&src->prs);
207 /*******************************************************************
208 Get the size of a BUFFER struct.
209 ********************************************************************/
211 uint32 rpcbuf_get_size(RPC_BUFFER *buffer)
213 return (buffer->size);
217 /*******************************************************************
218 * write a UNICODE string and its relative pointer.
219 * used by all the RPC structs passing a buffer
221 * As I'm a nice guy, I'm forcing myself to explain this code.
222 * MS did a good job in the overall spoolss code except in some
223 * functions where they are passing the API buffer directly in the
224 * RPC request/reply. That's to maintain compatiility at the API level.
225 * They could have done it the good way the first time.
227 * So what happen is: the strings are written at the buffer's end,
228 * in the reverse order of the original structure. Some pointers to
229 * the strings are also in the buffer. Those are relative to the
232 * If you don't understand or want to change that function,
233 * first get in touch with me: jfm@samba.org
235 ********************************************************************/
237 BOOL smb_io_relstr(const char *desc, RPC_BUFFER *buffer, int depth, UNISTR *string)
239 prs_struct *ps=&buffer->prs;
241 if (MARSHALLING(ps)) {
242 uint32 struct_offset = prs_offset(ps);
243 uint32 relative_offset;
245 buffer->string_at_end -= (size_of_relative_string(string) - 4);
246 if(!prs_set_offset(ps, buffer->string_at_end))
250 * Win2k does not align strings in a buffer
251 * Tested against WinNT 4.0 SP 6a & 2k SP2 --jerry
256 buffer->string_at_end = prs_offset(ps);
258 /* write the string */
259 if (!smb_io_unistr(desc, string, ps, depth))
262 if(!prs_set_offset(ps, struct_offset))
265 relative_offset=buffer->string_at_end - buffer->struct_start;
266 /* write its offset */
267 if (!prs_uint32("offset", ps, depth, &relative_offset))
273 /* read the offset */
274 if (!prs_uint32("offset", ps, depth, &(buffer->string_at_end)))
277 if (buffer->string_at_end == 0)
280 old_offset = prs_offset(ps);
281 if(!prs_set_offset(ps, buffer->string_at_end+buffer->struct_start))
284 /* read the string */
285 if (!smb_io_unistr(desc, string, ps, depth))
288 if(!prs_set_offset(ps, old_offset))
294 /*******************************************************************
295 * write a array of UNICODE strings and its relative pointer.
296 * used by 2 RPC structs
297 ********************************************************************/
299 BOOL smb_io_relarraystr(const char *desc, RPC_BUFFER *buffer, int depth, uint16 **string)
303 prs_struct *ps=&buffer->prs;
305 if (MARSHALLING(ps)) {
306 uint32 struct_offset = prs_offset(ps);
307 uint32 relative_offset;
314 /* first write the last 0 */
315 buffer->string_at_end -= 2;
316 if(!prs_set_offset(ps, buffer->string_at_end))
319 if(!prs_uint16("leading zero", ps, depth, &zero))
322 while (p && (*p!=0)) {
326 /* Yes this should be malloc not talloc. Don't change. */
328 chaine.buffer = SMB_MALLOC((q-p+1)*sizeof(uint16));
329 if (chaine.buffer == NULL)
332 memcpy(chaine.buffer, p, (q-p+1)*sizeof(uint16));
334 buffer->string_at_end -= (q-p+1)*sizeof(uint16);
336 if(!prs_set_offset(ps, buffer->string_at_end)) {
337 SAFE_FREE(chaine.buffer);
341 /* write the string */
342 if (!smb_io_unistr(desc, &chaine, ps, depth)) {
343 SAFE_FREE(chaine.buffer);
349 SAFE_FREE(chaine.buffer);
352 if(!prs_set_offset(ps, struct_offset))
355 relative_offset=buffer->string_at_end - buffer->struct_start;
356 /* write its offset */
357 if (!prs_uint32("offset", ps, depth, &relative_offset))
365 uint16 *chaine2=NULL;
368 size_t realloc_size = 0;
372 /* read the offset */
373 if (!prs_uint32("offset", ps, depth, &buffer->string_at_end))
376 old_offset = prs_offset(ps);
377 if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start))
381 if (!smb_io_unistr(desc, &chaine, ps, depth))
384 l_chaine=str_len_uni(&chaine);
386 /* we're going to add two more bytes here in case this
387 is the last string in the array and we need to add
388 an extra NULL for termination */
393 realloc_size = (l_chaine2+l_chaine+2)*sizeof(uint16);
395 /* Yes this should be realloc - it's freed below. JRA */
397 if((tc2=(uint16 *)SMB_REALLOC(chaine2, realloc_size)) == NULL) {
402 memcpy(chaine2+l_chaine2, chaine.buffer, (l_chaine+1)*sizeof(uint16));
403 l_chaine2+=l_chaine+1;
406 } while(l_chaine!=0);
408 /* the end should be bould NULL terminated so add
409 the second one here */
412 chaine2[l_chaine2] = '\0';
413 *string=(uint16 *)TALLOC_MEMDUP(prs_get_mem_context(ps),chaine2,realloc_size);
417 if(!prs_set_offset(ps, old_offset))
423 /*******************************************************************
424 Parse a DEVMODE structure and its relative pointer.
425 ********************************************************************/
427 BOOL smb_io_relsecdesc(const char *desc, RPC_BUFFER *buffer, int depth, SEC_DESC **secdesc)
429 prs_struct *ps= &buffer->prs;
431 prs_debug(ps, depth, desc, "smb_io_relsecdesc");
434 if (MARSHALLING(ps)) {
435 uint32 struct_offset = prs_offset(ps);
436 uint32 relative_offset;
440 if (!prs_uint32("offset", ps, depth, &relative_offset))
445 if (*secdesc != NULL) {
446 buffer->string_at_end -= sec_desc_size(*secdesc);
448 if(!prs_set_offset(ps, buffer->string_at_end))
450 /* write the secdesc */
451 if (!sec_io_desc(desc, secdesc, ps, depth))
454 if(!prs_set_offset(ps, struct_offset))
458 relative_offset=buffer->string_at_end - buffer->struct_start;
459 /* write its offset */
461 if (!prs_uint32("offset", ps, depth, &relative_offset))
466 /* read the offset */
467 if (!prs_uint32("offset", ps, depth, &buffer->string_at_end))
470 old_offset = prs_offset(ps);
471 if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start))
475 if (!sec_io_desc(desc, secdesc, ps, depth))
478 if(!prs_set_offset(ps, old_offset))
486 /*******************************************************************
487 * return the length of a UNICODE string in number of char, includes:
489 * - the relative pointer size
490 ********************************************************************/
492 uint32 size_of_relative_string(UNISTR *string)
496 size=str_len_uni(string); /* the string length */
497 size=size+1; /* add the trailing zero */
498 size=size*2; /* convert in char */
499 size=size+4; /* add the size of the ptr */
503 * Do not include alignment as Win2k does not align relative
504 * strings within a buffer --jerry
506 /* Ensure size is 4 byte multiple (prs_align is being called...). */
507 /* size += ((4 - (size & 3)) & 3); */