/*
* Unix SMB/CIFS implementation.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-2000,
* Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
* Copyright (C) Jean François Micouleau 1998-2000,
* Copyright (C) Gerald Carter 2000-2002,
* Copyright (C) Tim Potter 2001-2002.
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
#include "includes.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_PARSE
/*******************************************************************
* return the length of a uint32 (obvious, but the code is clean)
********************************************************************/
static uint32 size_of_uint32(uint32 *value)
{
return (sizeof(*value));
}
/*******************************************************************
return the size required by a struct in the stream
********************************************************************/
uint32 spoolss_size_printer_enum_values(PRINTER_ENUM_VALUES *p)
{
uint32 size = 0;
if (!p)
return 0;
/* uint32(offset) + uint32(length) + length) */
size += (size_of_uint32(&p->value_len)*2) + p->value_len;
size += (size_of_uint32(&p->data_len)*2) + p->data_len + (p->data_len%2) ;
size += size_of_uint32(&p->type);
return size;
}
/*******************************************************************
make a BUFFER5 struct from a uint16*
******************************************************************/
bool make_spoolss_buffer5(TALLOC_CTX *mem_ctx, BUFFER5 *buf5, uint32 len, uint16 *src)
{
buf5->buf_len = len;
if (src) {
if (len) {
if((buf5->buffer=(uint16*)TALLOC_MEMDUP(mem_ctx, src, sizeof(uint16)*len)) == NULL) {
DEBUG(0,("make_spoolss_buffer5: Unable to malloc memory for buffer!\n"));
return False;
}
} else {
buf5->buffer = NULL;
}
} else {
buf5->buffer=NULL;
}
return True;
}
/*******************************************************************
********************************************************************/
bool make_spoolss_q_enumprinterdataex(SPOOL_Q_ENUMPRINTERDATAEX *q_u,
const POLICY_HND *hnd, const char *key,
uint32 size)
{
memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
init_unistr2(&q_u->key, key, UNI_STR_TERMINATE);
q_u->size = size;
return True;
}
/*******************************************************************
* read a structure.
********************************************************************/
bool spoolss_io_q_enumprinterdataex(const char *desc, SPOOL_Q_ENUMPRINTERDATAEX *q_u, prs_struct *ps, int depth)
{
prs_debug(ps, depth, desc, "spoolss_io_q_enumprinterdataex");
depth++;
if(!prs_align(ps))
return False;
if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth))
return False;
if(!smb_io_unistr2("", &q_u->key, True, ps, depth))
return False;
if(!prs_align(ps))
return False;
if(!prs_uint32("size", ps, depth, &q_u->size))
return False;
return True;
}
/*******************************************************************
********************************************************************/
static bool spoolss_io_printer_enum_values_ctr(const char *desc, prs_struct *ps,
PRINTER_ENUM_VALUES_CTR *ctr, int depth)
{
int i;
uint32 valuename_offset,
data_offset,
current_offset;
const uint32 basic_unit = 20; /* size of static portion of enum_values */
prs_debug(ps, depth, desc, "spoolss_io_printer_enum_values_ctr");
depth++;
/*
* offset data begins at 20 bytes per structure * size_of_array.
* Don't forget the uint32 at the beginning
* */
current_offset = basic_unit * ctr->size_of_array;
/* first loop to write basic enum_value information */
if (UNMARSHALLING(ps) && ctr->size_of_array) {
ctr->values = PRS_ALLOC_MEM(ps, PRINTER_ENUM_VALUES, ctr->size_of_array);
if (!ctr->values)
return False;
}
for (i=0; isize_of_array; i++) {
uint32 base_offset, return_offset;
base_offset = prs_offset(ps);
valuename_offset = current_offset;
if (!prs_uint32("valuename_offset", ps, depth, &valuename_offset))
return False;
/* Read or write the value. */
return_offset = prs_offset(ps);
if (!prs_set_offset(ps, base_offset + valuename_offset)) {
return False;
}
if (!prs_unistr("valuename", ps, depth, &ctr->values[i].valuename))
return False;
/* And go back. */
if (!prs_set_offset(ps, return_offset))
return False;
if (!prs_uint32("value_len", ps, depth, &ctr->values[i].value_len))
return False;
if (!prs_uint32("type", ps, depth, &ctr->values[i].type))
return False;
data_offset = ctr->values[i].value_len + valuename_offset;
if (!prs_uint32("data_offset", ps, depth, &data_offset))
return False;
if (!prs_uint32("data_len", ps, depth, &ctr->values[i].data_len))
return False;
/* Read or write the data. */
return_offset = prs_offset(ps);
if (!prs_set_offset(ps, base_offset + data_offset)) {
return False;
}
if ( ctr->values[i].data_len ) {
if ( UNMARSHALLING(ps) ) {
ctr->values[i].data = PRS_ALLOC_MEM(ps, uint8, ctr->values[i].data_len);
if (!ctr->values[i].data)
return False;
}
if (!prs_uint8s(False, "data", ps, depth, ctr->values[i].data, ctr->values[i].data_len))
return False;
}
current_offset = data_offset + ctr->values[i].data_len - basic_unit;
/* account for 2 byte alignment */
current_offset += (current_offset % 2);
/* Remember how far we got. */
data_offset = prs_offset(ps);
/* And go back. */
if (!prs_set_offset(ps, return_offset))
return False;
}
/* Go to the last data offset we got to. */
if (!prs_set_offset(ps, data_offset))
return False;
/* And ensure we're 2 byte aligned. */
if ( !prs_align_uint16(ps) )
return False;
return True;
}
/*******************************************************************
* write a structure.
********************************************************************/
bool spoolss_io_r_enumprinterdataex(const char *desc, SPOOL_R_ENUMPRINTERDATAEX *r_u, prs_struct *ps, int depth)
{
uint32 data_offset, end_offset;
prs_debug(ps, depth, desc, "spoolss_io_r_enumprinterdataex");
depth++;
if(!prs_align(ps))
return False;
if (!prs_uint32("size", ps, depth, &r_u->ctr.size))
return False;
data_offset = prs_offset(ps);
if (!prs_set_offset(ps, data_offset + r_u->ctr.size))
return False;
if(!prs_align(ps))
return False;
if(!prs_uint32("needed", ps, depth, &r_u->needed))
return False;
if(!prs_uint32("returned", ps, depth, &r_u->returned))
return False;
if(!prs_werror("status", ps, depth, &r_u->status))
return False;
r_u->ctr.size_of_array = r_u->returned;
end_offset = prs_offset(ps);
if (!prs_set_offset(ps, data_offset))
return False;
if (r_u->ctr.size)
if (!spoolss_io_printer_enum_values_ctr("", ps, &r_u->ctr, depth ))
return False;
if (!prs_set_offset(ps, end_offset))
return False;
return True;
}