diff options
Diffstat (limited to 'source3/rpc_parse/parse_prs.c')
-rw-r--r-- | source3/rpc_parse/parse_prs.c | 787 |
1 files changed, 417 insertions, 370 deletions
diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index d9c07e3885..f5f4eb67b8 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -2,8 +2,9 @@ Unix SMB/Netbios implementation. Version 1.9. Samba memory buffer functions - Copyright (C) Andrew Tridgell 1992-1999 - Copyright (C) Luke Kenneth Casson Leighton 1996-1999 + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Jeremy Allison 1999. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,523 +34,567 @@ extern int DEBUGLEVEL; ********************************************************************/ void prs_debug(prs_struct *ps, int depth, char *desc, char *fn_name) { - DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->offset, fn_name, desc)); + DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->data_offset, fn_name, desc)); } /******************************************************************* - debug a parse structure + Initialise a parse structure - malloc the data if requested. ********************************************************************/ -void prs_debug_out(prs_struct *ps, char *msg, int level) + +BOOL prs_init(prs_struct *ps, uint32 size, uint8 align, BOOL io) { - DEBUG(level,("%s ps: io %s align %d offset %d err %d data %p len %d\n", - msg, BOOLSTR(ps->io), ps->align, ps->offset, ps->error, - ps->data, - ps->data != NULL ? mem_buf_len(ps->data) : 0)); + ZERO_STRUCTP(ps); + ps->io = io; + ps->bigendian_data = False; + ps->align = align; + ps->is_dynamic = False; + ps->data_offset = 0; + ps->buffer_size = 0; + ps->data_p = NULL; + + if (size != 0) { + ps->buffer_size = size; + if((ps->data_p = (char *)malloc((size_t)size)) == NULL) { + DEBUG(0,("prs_init: malloc fail for %u bytes.\n", (unsigned int)size)); + return False; + } + ps->is_dynamic = True; /* We own this memory. */ + } + + return True; } /******************************************************************* - initialise a parse structure + Delete the memory in a parse structure - if we own it. ********************************************************************/ -void prs_init(prs_struct *ps, uint32 size, - uint8 align, uint32 margin, - BOOL io) + +void prs_mem_free(prs_struct *ps) { - ps->io = io; - ps->align = align; - ps->offset = 0; - ps->error = False; + if(ps->is_dynamic && (ps->data_p != NULL)) + free(ps->data_p); + ps->is_dynamic = False; + ps->data_p = NULL; + ps->buffer_size = 0; + ps->data_offset = 0; +} - ps->data = NULL; - mem_buf_init(&(ps->data), margin); +/******************************************************************* + Hand some already allocated memory to a prs_struct. + ********************************************************************/ - if (size != 0) - { - mem_alloc_data(ps->data, size); - ps->data->offset.start = 0; - ps->data->offset.end = 0xffffffff; - } +void prs_give_memory(prs_struct *ps, char *buf, uint32 size, BOOL is_dynamic) +{ + ps->is_dynamic = is_dynamic; + ps->data_p = buf; + ps->buffer_size = size; } /******************************************************************* - copy a parse structure + Take some memory back from a prs_struct. ********************************************************************/ -BOOL prs_copy(prs_struct *ps, const prs_struct *from) + +char *prs_take_memory(prs_struct *ps, uint32 *psize) { - int len = mem_buf_len(from->data); - prs_init(ps, len, from->align, from->data->margin, from->io); - if (!mem_buf_copy(mem_data(&ps->data, 0), from->data, 0, len)) - { + char *ret = ps->data_p; + if(psize) + *psize = ps->buffer_size; + ps->is_dynamic = False; + prs_mem_free(ps); + return ret; +} + +/******************************************************************* + Attempt, if needed, to grow a data buffer. + Also depends on the data stream mode (io). + ********************************************************************/ + +BOOL prs_grow(prs_struct *ps, uint32 extra_space) +{ + uint32 new_size; + char *new_data; + + if(ps->data_offset + extra_space <= ps->buffer_size) + return True; + + /* + * We cannot grow the buffer if we're not reading + * into the prs_struct, or if we don't own the memory. + */ + + if(UNMARSHALLING(ps) || !ps->is_dynamic) { + DEBUG(0,("prs_grow: Buffer overflow - unable to expand buffer by %u bytes.\n", + (unsigned int)extra_space)); return False; } - ps->offset = len; - prs_link(NULL, ps, NULL); + + /* + * Decide how much extra space we really need. + */ + + extra_space -= (ps->buffer_size - ps->data_offset); + + if(ps->buffer_size == 0) { + + /* + * Ensure we have at least a PDU's length, or extra_space, whichever + * is greater. + */ + + new_size = MAX(MAX_PDU_FRAG_LEN,extra_space); + + if((new_data = malloc(new_size)) == NULL) { + DEBUG(0,("prs_grow: Malloc failure for size %u.\n", (unsigned int)new_size)); + return False; + } + memset(new_data, '\0', new_size ); + } else { + + /* + * If the current buffer size is bigger than the space needed, just + * double it, else add extra_space. + */ + + new_size = MAX(ps->buffer_size*2, ps->buffer_size + extra_space); + + if((new_data = Realloc(ps->data_p, new_size)) == NULL) { + DEBUG(0,("prs_grow: Realloc failure for size %u.\n", + (unsigned int)new_size)); + return False; + } + } + + ps->buffer_size = new_size; + ps->data_p = new_data; + return True; } /******************************************************************* - initialise a parse structure + Attempt to force a data buffer to grow by len bytes. + This is only used when appending more data onto a prs_struct + when reading an rpc reply, before unmarshalling it. ********************************************************************/ -void prs_mem_free(prs_struct *ps) + +BOOL prs_force_grow(prs_struct *ps, uint32 extra_space) { - mem_buf_free(&(ps->data)); + uint32 new_size = ps->buffer_size + extra_space; + char *new_data; + + if(!UNMARSHALLING(ps) || !ps->is_dynamic) { + DEBUG(0,("prs_force_grow: Buffer overflow - unable to expand buffer by %u bytes.\n", + (unsigned int)extra_space)); + return False; + } + + if((new_data = Realloc(ps->data_p, new_size)) == NULL) { + DEBUG(0,("prs_force_grow: Realloc failure for size %u.\n", + (unsigned int)new_size)); + return False; + } + + ps->buffer_size = new_size; + ps->data_p = new_data; + + return True; } /******************************************************************* - link one parsing structure to another + Get the data pointer (external interface). ********************************************************************/ -void prs_link(prs_struct *prev, prs_struct *ps, prs_struct *next) -{ - ps->data->offset.start = prev != NULL ? prev->data->offset.end : 0; - ps->data->offset.end = ps->data->offset.start + ps->offset; - ps->data->next = next != NULL ? next->data : NULL; - DEBUG(150,("prs_link: start %d end %d\n", - ps->data->offset.start, - ps->data->offset.end)); +char *prs_data_p(prs_struct *ps) +{ + return ps->data_p; } /******************************************************************* - align a pointer to a multiple of align_offset bytes. looks like it - will work for offsets of 0, 2 and 4... + Get the current data size (external interface). ********************************************************************/ -void prs_align(prs_struct *ps) + +uint32 prs_data_size(prs_struct *ps) { - int mod; - if (ps->error) return; - mod = ps->offset & (ps->align-1); - if (ps->align != 0 && mod != 0) - { - ps->offset += ps->align - mod; - } + return ps->buffer_size; } /******************************************************************* - attempt, if appropriate, to grow a data buffer. - - depends on the data stream mode (io) + Fetch the current offset (external interface). ********************************************************************/ -BOOL prs_grow(prs_struct *ps, uint32 new_size) + +uint32 prs_offset(prs_struct *ps) { - if (ps->error) return False; - return mem_grow_data(&(ps->data), ps->io, new_size, False); + return ps->data_offset; } /******************************************************************* - lengthens a buffer by len bytes and copies data into it. + Set the current offset (external interface). ********************************************************************/ -BOOL prs_append_data(prs_struct *ps, const char *data, int len) + +BOOL prs_set_offset(prs_struct *ps, uint32 offset) { - int prev_size = ps->data->data_used; - int new_size = prev_size + len; - char *to; + if(offset <= ps->data_offset) { + ps->data_offset = offset; + return True; + } - mem_realloc_data(ps->data, new_size); - to = mem_data(&ps->data, prev_size); - if (to == NULL || ps->data->data_used != new_size) - { + if(!prs_grow(ps, offset - ps->data_offset)) return False; - } - memcpy(to, data, len); + ps->data_offset = offset; return True; } /******************************************************************* - stream a uint8 + Append the data from one parse_struct into another. ********************************************************************/ -BOOL _prs_uint8(char *name, prs_struct *ps, int depth, uint8 *data8) + +BOOL prs_append_prs_data(prs_struct *dst, prs_struct *src) { - char *q; - if (ps->error) return False; - prs_grow(ps, ps->offset + 1); - q = mem_data(&(ps->data), ps->offset); - if (q == NULL) - { - ps->error = True; - prs_debug_out(ps, "_prs_uint8 error", 5); + if(!prs_grow(dst, prs_offset(src))) return False; - } - - DBG_RW_CVAL(name, depth, ps->offset, ps->io, q, *data8) - ps->offset += 1; + memcpy(&dst->data_p[dst->data_offset], prs_data_p(src), (size_t)prs_offset(src)); + dst->data_offset += prs_offset(src); return True; } /******************************************************************* - stream a uint16 + Append the data from a buffer into a parse_struct. ********************************************************************/ -BOOL _prs_uint16(char *name, prs_struct *ps, int depth, uint16 *data16) + +BOOL prs_append_data(prs_struct *dst, char *src, uint32 len) { - char *q; - if (ps->error) return False; - prs_grow(ps, ps->offset + 2); - q = mem_data(&(ps->data), ps->offset); - if (q == NULL) - { - ps->error = True; - prs_debug_out(ps, "_prs_uint16 error", 5); + if(!prs_grow(dst, len)) return False; - } - DBG_RW_SVAL(name, depth, ps->offset, ps->io, q, *data16) - ps->offset += 2; + memcpy(&dst->data_p[dst->data_offset], src, (size_t)len); + dst->data_offset += len; return True; } /******************************************************************* - hash a stream. + Set the data as big-endian (external interface). ********************************************************************/ -BOOL _prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16]) + +void prs_set_bigendian_data(prs_struct *ps) { - char *q; - if (ps->error) return False; - q = mem_data(&(ps->data), ps->offset); + ps->bigendian_data = True; +} + +/******************************************************************* + Align a the data_len to a multiple of align bytes - filling with + zeros. + ********************************************************************/ + +BOOL prs_align(prs_struct *ps) +{ + uint32 mod = ps->data_offset & (ps->align-1); + + if (ps->align != 0 && mod != 0) { + uint32 extra_space = (ps->align - mod); + if(!prs_grow(ps, extra_space)) + return False; + memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space); + ps->data_offset += extra_space; + } + + return True; +} + +/******************************************************************* + Ensure we can read/write to a given offset. + ********************************************************************/ + +char *prs_mem_get(prs_struct *ps, uint32 extra_size) +{ + if(UNMARSHALLING(ps)) { + /* + * If reading, ensure that we can read the requested size item. + */ + if (ps->data_offset + extra_size > ps->buffer_size) { + DEBUG(0,("prs_mem_get: reading data of size %u would overrun buffer.\n", + (unsigned int)extra_size )); + return NULL; + } + } else { + /* + * Writing - grow the buffer if needed. + */ + if(!prs_grow(ps, extra_size)) + return False; + } + return &ps->data_p[ps->data_offset]; +} + +/******************************************************************* + Stream a uint8. + ********************************************************************/ + +BOOL prs_uint8(char *name, prs_struct *ps, int depth, uint8 *data8) +{ + char *q = prs_mem_get(ps, sizeof(uint8)); if (q == NULL) - { - ps->error = True; - prs_debug_out(ps, "_prs_hash1 error", 5); return False; - } -#ifdef DEBUG_PASSWORD - DEBUG(100,("prs_hash1\n")); - dump_data(100, sess_key, 16); - dump_data(100, q, 68); -#endif - SamOEMhash((uchar*)q, sess_key, 2); -#ifdef DEBUG_PASSWORD - dump_data(100, q, 68); -#endif + DBG_RW_CVAL(name, depth, ps->data_offset, ps->io, q, *data8) + ps->data_offset += sizeof(uint8); return True; } /******************************************************************* - stream a uint32 + Stream a uint16. ********************************************************************/ -BOOL _prs_uint32(char *name, prs_struct *ps, int depth, uint32 *data32) + +BOOL prs_uint16(char *name, prs_struct *ps, int depth, uint16 *data16) { - char *q; - if (ps->error) return False; - prs_grow(ps, ps->offset + 4); - q = mem_data(&(ps->data), ps->offset); + char *q = prs_mem_get(ps, sizeof(uint16)); if (q == NULL) - { - ps->error = True; - prs_debug_out(ps, "_prs_uint32 error", 5); return False; - } - DBG_RW_IVAL(name, depth, ps->offset, ps->io, q, *data32) - ps->offset += 4; + DBG_RW_SVAL(name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, *data16) + ps->data_offset += sizeof(uint16); return True; } - -/****************************************************************** - stream an array of uint8s. length is number of uint8s +/******************************************************************* + Stream a uint32. ********************************************************************/ -BOOL _prs_uint8s(BOOL charmode, char *name, prs_struct *ps, int depth, uint8 *data8s, int len) + +BOOL prs_uint32(char *name, prs_struct *ps, int depth, uint32 *data32) { - char *q; - int end_offset; - char *e; - if (ps->error) return False; - end_offset = ps->offset + len * sizeof(uint8); - prs_grow(ps, end_offset); - q = mem_data(&(ps->data), ps->offset); - e = mem_data(&(ps->data), end_offset-1); - - if (q == NULL || e == NULL) - { - ps->error = True; - prs_debug_out(ps, "_prs_uint8s error", 5); + char *q = prs_mem_get(ps, sizeof(uint32)); + if (q == NULL) return False; - } - DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, data8s, len) - ps->offset = end_offset; + DBG_RW_IVAL(name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, *data32) + ps->data_offset += sizeof(uint32); return True; } + /****************************************************************** - stream an array of uint16s. length is number of uint16s + Stream an array of uint8s. Length is number of uint8s. ********************************************************************/ -BOOL _prs_uint16s(BOOL charmode, char *name, prs_struct *ps, int depth, uint16 *data16s, int len) + +BOOL prs_uint8s(BOOL charmode, char *name, prs_struct *ps, int depth, uint8 *data8s, int len) { - char *q; - int end_offset; - char *e; - if (ps->error) return False; - end_offset = ps->offset + len * sizeof(uint16); - prs_grow(ps, end_offset); - q = mem_data(&(ps->data), ps->offset); - e = mem_data(&(ps->data), end_offset-1); - - if (q == NULL || e == NULL) - { - ps->error = True; - prs_debug_out(ps, "_prs_uint16s error", 5); + char *q = prs_mem_get(ps, len * sizeof(uint8)); + if (q == NULL) return False; - } - DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, data16s, len) - ps->offset = end_offset; + DBG_RW_PCVAL(charmode, name, depth, ps->data_offset, ps->io, q, data8s, len) + ps->data_offset += (len * sizeof(uint8)); return True; } /****************************************************************** - stream an array of uint32s. length is number of uint32s + Stream an array of uint32s. Length is number of uint32s. ********************************************************************/ -BOOL _prs_uint32s(BOOL charmode, char *name, prs_struct *ps, int depth, uint32 *data32s, int len) + +BOOL prs_uint32s(BOOL charmode, char *name, prs_struct *ps, int depth, uint32 *data32s, int len) { - char *q; - int end_offset; - char *e; - if (ps->error) return False; - end_offset = ps->offset + len * sizeof(uint32); - prs_grow(ps, end_offset); - q = mem_data(&(ps->data), ps->offset); - e = mem_data(&(ps->data), end_offset-1); - - if (q == NULL || e == NULL) - { - ps->error = True; - prs_debug_out(ps, "_prs_uint32s error", 5); + char *q = prs_mem_get(ps, len * sizeof(uint32)); + if (q == NULL) return False; - } - DBG_RW_PIVAL(charmode, name, depth, ps->offset, ps->io, q, data32s, len) - ps->offset = end_offset; + DBG_RW_PIVAL(charmode, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, data32s, len) + ps->data_offset += (len * sizeof(uint32)); return True; } /****************************************************************** - stream a "not" unicode string, length/buffer specified separately, - in byte chars + Stream a "not" unicode string, length/buffer specified separately, + in byte chars. String is in little-endian format. ********************************************************************/ -BOOL _prs_buffer2(BOOL charmode, char *name, prs_struct *ps, int depth, BUFFER2 *str) + +BOOL prs_buffer2(BOOL charmode, char *name, prs_struct *ps, int depth, BUFFER2 *str) { - char *q; - int end_offset; - char *e; - if (ps->error) return False; - end_offset = ps->offset + str->buf_len * sizeof(uint8); - prs_grow(ps, end_offset); - q = mem_data(&(ps->data), ps->offset); - e = mem_data(&(ps->data), end_offset-1); - - if (q == NULL || e == NULL) - { - ps->error = True; - prs_debug_out(ps, "_prs_buffer2 error", 5); + char *p = (char *)str->buffer; + char *q = prs_mem_get(ps, str->buf_len); + if (q == NULL) return False; - } - DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->buf_len) - ps->offset = end_offset; + /* If we're using big-endian, reverse to get little-endian. */ + if(ps->bigendian_data) + DBG_RW_PSVAL(charmode, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, p, str->buf_len/2) + else + DBG_RW_PCVAL(charmode, name, depth, ps->data_offset, ps->io, q, p, str->buf_len) + ps->data_offset += str->buf_len; return True; } /****************************************************************** - stream a string, length/buffer specified separately, + Stream a string, length/buffer specified separately, in uint8 chars. ********************************************************************/ -BOOL _prs_string2(BOOL charmode, char *name, prs_struct *ps, int depth, STRING2 *str) + +BOOL prs_string2(BOOL charmode, char *name, prs_struct *ps, int depth, STRING2 *str) { - char *q; - int end_offset; - char *e; - if (ps->error) return False; - end_offset = ps->offset + str->str_str_len * sizeof(uint8); - prs_grow(ps, end_offset); - q = mem_data(&(ps->data), ps->offset); - e = mem_data(&(ps->data), end_offset-1); - - if (q == NULL || e == NULL) - { - ps->error = True; - prs_debug_out(ps, "_prs_string2 error", 5); + char *q = prs_mem_get(ps, str->str_str_len * sizeof(uint8)); + if (q == NULL) return False; - } - DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->str_max_len) - ps->offset = end_offset; + DBG_RW_PCVAL(charmode, name, depth, ps->data_offset, ps->io, q, str->buffer, str->str_max_len) + ps->data_offset += (str->str_str_len * sizeof(uint8)); return True; } /****************************************************************** - stream a unicode string, length/buffer specified separately, - in uint16 chars. + Stream a unicode string, length/buffer specified separately, + in uint16 chars. We use DBG_RW_PCVAL, not DBG_RW_PSVAL here + as the unicode string is already in little-endian format. ********************************************************************/ -BOOL _prs_unistr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNISTR2 *str) + +BOOL prs_unistr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNISTR2 *str) { - char *q; - int end_offset; - char *e; - if (ps->error) return False; - end_offset = ps->offset + str->uni_str_len * sizeof(uint16); - prs_grow(ps, end_offset); - q = mem_data(&(ps->data), ps->offset); - e = mem_data(&(ps->data), end_offset-1); - - if (q == NULL || e == NULL) - { - ps->error = True; - prs_debug_out(ps, "_prs_unistr2 error", 5); + char *p = (char *)str->buffer; + char *q = prs_mem_get(ps, str->uni_str_len * sizeof(uint16)); + if (q == NULL) return False; - } - DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->uni_str_len) - ps->offset = end_offset; + /* If we're using big-endian, reverse to get little-endian. */ + if(ps->bigendian_data) + DBG_RW_PSVAL(charmode, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, p, str->uni_str_len) + else + DBG_RW_PCVAL(charmode, name, depth, ps->data_offset, ps->io, q, p, str->uni_str_len * 2) + ps->data_offset += (str->uni_str_len * sizeof(uint16)); return True; } /****************************************************************** - stream a unicode string, length/buffer specified separately, - in uint16 chars. + Stream a unicode string, length/buffer specified separately, + in uint16 chars. We use DBG_RW_PCVAL, not DBG_RW_PSVAL here + as the unicode string is already in little-endian format. ********************************************************************/ -BOOL _prs_unistr3(BOOL charmode, char *name, UNISTR3 *str, prs_struct *ps, int depth) + +BOOL prs_unistr3(BOOL charmode, char *name, UNISTR3 *str, prs_struct *ps, int depth) { - char *q; - int end_offset; - char *e; - if (ps->error) return False; - end_offset = ps->offset + str->uni_str_len * sizeof(uint16); - prs_grow(ps, end_offset); - q = mem_data(&(ps->data), ps->offset); - e = mem_data(&(ps->data), end_offset-1); - - if (q == NULL || e == NULL) - { - ps->error = True; - prs_debug_out(ps, "_prs_unistr3 error", 5); + char *p = (char *)str->str.buffer; + char *q = prs_mem_get(ps, str->uni_str_len * sizeof(uint16)); + if (q == NULL) return False; - } - DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, str->str.buffer, str->uni_str_len) - ps->offset = end_offset; + /* If we're using big-endian, reverse to get little-endian. */ + if(ps->bigendian_data) + DBG_RW_PSVAL(charmode, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, p, str->uni_str_len) + else + DBG_RW_PCVAL(charmode, name, depth, ps->data_offset, ps->io, q, p, str->uni_str_len * 2) + ps->data_offset += (str->uni_str_len * sizeof(uint16)); return True; } /******************************************************************* - stream a unicode null-terminated string + Stream a unicode null-terminated string. As the string is already + in little-endian format then do it as a stream of bytes. ********************************************************************/ -BOOL _prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str) + +BOOL prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str) { - int i = -1; + int len = 0; + unsigned char *p = (unsigned char *)str->buffer; uint8 *start; - if (ps->error) return False; - start = (uint8*)mem_data(&(ps->data), ps->offset); + char *q; + + for(len = 0; len < (sizeof(str->buffer) / sizeof(str->buffer[0])) && + str->buffer[len] != 0; len++) + ; - do + q = prs_mem_get(ps, len*2); + if (q == NULL) + return False; + + start = (uint8*)q; + + len = 0; + do { - char *q; - i++; - prs_grow(ps, ps->offset + i*2); - q = mem_data(&(ps->data), ps->offset + i*2); - if (q == NULL) - { - ps->error = True; - prs_debug_out(ps, "_prs_unistr error", 5); - return False; + if(ps->bigendian_data) { + RW_SVAL(ps->io, ps->bigendian_data, q, *p, 0) + p += 2; + q += 2; + } else { + RW_CVAL(ps->io, q, *p, 0); + p++; + q++; + RW_CVAL(ps->io, q, *p, 0); + p++; + q++; } - RW_SVAL(ps->io, q, str->buffer[i],0); - } - while ((((size_t)i) < sizeof(str->buffer) / sizeof(str->buffer[0])) && - (str->buffer[i] != 0)); - + len++; + } while ((len < (sizeof(str->buffer) / sizeof(str->buffer[0]))) && + (str->buffer[len] != 0)); - ps->offset += (i+1)*2; + ps->data_offset += len*2; - dump_data(5+depth, (char *)start, i * 2); + dump_data(5+depth, (char *)start, len * 2); return True; } /******************************************************************* - stream a null-terminated string. len is strlen, and therefore does + Stream a null-terminated string. len is strlen, and therefore does not include the null-termination character. - - len == 0 indicates variable length string - (up to max size of pstring - 1024 chars). - ********************************************************************/ -BOOL _prs_string(char *name, prs_struct *ps, int depth, char *str, uint16 len, uint16 max_buf_size) + +BOOL prs_string(char *name, prs_struct *ps, int depth, char *str, int len, int max_buf_size) { - int i = -1; /* start off at zero after 1st i++ */ + char *q; uint8 *start; - if (ps->error) return False; - start = (uint8*)mem_data(&(ps->data), ps->offset); + int i; - DEBUG(120,("_prs_string: string %s len %d max %d\n", - str, len, max_buf_size)); + len = MIN(len, (max_buf_size-1)); - DEBUG(10,("%s%04x %s: ", tab_depth(depth), ps->offset, name != NULL ? name : "")); + q = prs_mem_get(ps, len+1); + if (q == NULL) + return False; - do - { - char *q; - i++; - - prs_grow(ps, ps->offset + i); - q = mem_data(&(ps->data), ps->offset + i); - if (q == NULL) - { - ps->error = True; - prs_debug_out(ps, "_prs_string error", 5); - return False; - } + start = (uint8*)q; - if (i < len || len == 0) - { - RW_CVAL(ps->io, q, str[i], 0); - } - else - { - uint8 dummy = 0; - RW_CVAL(ps->io, q, dummy,0); - } + for(i = 0; i < len; i++) { + RW_CVAL(ps->io, q, str[i],0); + q++; + } - } while (i < max_buf_size && (len == 0 ? str[i] != 0 : i < len) ); + /* The terminating null. */ + str[i] = '\0'; - DEBUG(120,("_prs_string: string %s len %d max %d\n", - str, len, max_buf_size)); + if (MARSHALLING(ps)) { + RW_CVAL(ps->io, q, str[i], 0); + } - ps->offset += i+1; + ps->data_offset += len+1; - dump_data(5+depth, (char *)start, i); + dump_data(5+depth, (char *)start, len); return True; } /******************************************************************* - prs_uint16 wrapper. call this and it sets up a pointer to where the - uint16 should be stored, or gets the size if reading + prs_uint16 wrapper. Call this and it sets up a pointer to where the + uint16 should be stored, or gets the size if reading. ********************************************************************/ -BOOL _prs_uint16_pre(char *name, prs_struct *ps, int depth, uint16 *data16, uint32 *offset) + +BOOL prs_uint16_pre(char *name, prs_struct *ps, int depth, uint16 *data16, uint32 *offset) { - if (ps->error) return False; - (*offset) = ps->offset; - if (ps->io) - { + (*offset) = ps->data_offset; + if (UNMARSHALLING(ps)) { /* reading. */ - return _prs_uint16(name, ps, depth, data16); - } - else - { - ps->offset += sizeof(uint16); + return prs_uint16(name, ps, depth, data16); + } else { + char *q = prs_mem_get(ps, sizeof(uint16)); + if(q ==NULL) + return False; + ps->data_offset += sizeof(uint16); } return True; } @@ -558,43 +603,42 @@ BOOL _prs_uint16_pre(char *name, prs_struct *ps, int depth, uint16 *data16, uint prs_uint16 wrapper. call this and it retrospectively stores the size. does nothing on reading, as that is already handled by ...._pre() ********************************************************************/ -BOOL _prs_uint16_post(char *name, prs_struct *ps, int depth, uint16 *data16, + +BOOL prs_uint16_post(char *name, prs_struct *ps, int depth, uint16 *data16, uint32 ptr_uint16, uint32 start_offset) { - if (ps->error) return False; - if (!ps->io) - { - /* storing: go back and do a retrospective job. i hate this */ - uint16 data_size = ps->offset - start_offset; - uint32 old_offset = ps->offset; - - ps->offset = ptr_uint16; - prs_uint16(name, ps, depth, &data_size); - ps->offset = old_offset; - } - else - { - ps->offset = start_offset + (*data16); + if (MARSHALLING(ps)) { + /* + * Writing - temporarily move the offset pointer. + */ + uint16 data_size = ps->data_offset - start_offset; + uint32 old_offset = ps->data_offset; + + ps->data_offset = ptr_uint16; + if(!prs_uint16(name, ps, depth, &data_size)) { + ps->data_offset = old_offset; + return False; + } + ps->data_offset = old_offset; + } else { + ps->data_offset = start_offset + (uint32)(*data16); } return True; } /******************************************************************* - prs_uint32 wrapper. call this and it sets up a pointer to where the - uint32 should be stored, or gets the size if reading + prs_uint32 wrapper. Call this and it sets up a pointer to where the + uint32 should be stored, or gets the size if reading. ********************************************************************/ -BOOL _prs_uint32_pre(char *name, prs_struct *ps, int depth, uint32 *data32, uint32 *offset) + +BOOL prs_uint32_pre(char *name, prs_struct *ps, int depth, uint32 *data32, uint32 *offset) { - if (ps->error) return False; - (*offset) = ps->offset; - if (ps->io) - { + (*offset) = ps->data_offset; + if (UNMARSHALLING(ps)) { /* reading. */ - return _prs_uint32(name, ps, depth, data32); - } - else - { - ps->offset += sizeof(uint32); + return prs_uint32(name, ps, depth, data32); + } else { + ps->data_offset += sizeof(uint32); } return True; } @@ -603,18 +647,21 @@ BOOL _prs_uint32_pre(char *name, prs_struct *ps, int depth, uint32 *data32, uint prs_uint32 wrapper. call this and it retrospectively stores the size. does nothing on reading, as that is already handled by ...._pre() ********************************************************************/ -BOOL _prs_uint32_post(char *name, prs_struct *ps, int depth, uint32 *data32, + +BOOL prs_uint32_post(char *name, prs_struct *ps, int depth, uint32 *data32, uint32 ptr_uint32, uint32 data_size) { - if (ps->error) return False; - if (!ps->io) - { - /* storing: go back and do a retrospective job. i hate this */ - uint32 old_offset = ps->offset; - ps->offset = ptr_uint32; - prs_uint32(name, ps, depth, &data_size); - ps->offset = old_offset; + if (MARSHALLING(ps)) { + /* + * Writing - temporarily move the offset pointer. + */ + uint32 old_offset = ps->data_offset; + ps->data_offset = ptr_uint32; + if(!prs_uint32(name, ps, depth, &data_size)) { + ps->data_offset = old_offset; + return False; + } + ps->data_offset = old_offset; } return True; } - |