summaryrefslogtreecommitdiffstats
path: root/librpc/wsp/wsp_util.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--librpc/wsp/wsp_util.c919
1 files changed, 919 insertions, 0 deletions
diff --git a/librpc/wsp/wsp_util.c b/librpc/wsp/wsp_util.c
new file mode 100644
index 0000000..fae6e0b
--- /dev/null
+++ b/librpc/wsp/wsp_util.c
@@ -0,0 +1,919 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Window Search Service
+ *
+ * Copyright (c) Noel Power
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+#include "includes.h"
+#include "librpc/wsp/wsp_util.h"
+#include "librpc/gen_ndr/wsp.h"
+#include "librpc/gen_ndr/ndr_wsp.h"
+#include "lib/util/strv_util.h"
+#include "lib/util/strv.h"
+#include "lib/util/util_str_hex.h"
+#include "source3/param/param_proto.h"
+#include "lib/util/dlinklist.h"
+
+#define BUFFER_SIZE 1024000
+struct guidtopropmap_holder
+{
+ struct guidtopropmap *guidtopropmaploc;
+};
+
+struct full_propset_info_list {
+ struct full_propset_info_list *prev, *next;
+ struct full_propset_info info;
+};
+
+struct guidtopropmap {
+ struct guidtopropmap *prev, *next;
+ struct GUID guid;
+ struct full_propset_info_list *propset;
+};
+
+static struct guidtopropmap *find_guid_props(
+ struct guidtopropmap_holder *holder,
+ const struct GUID *guid)
+{
+ struct guidtopropmap *mapitem;
+ for (mapitem = holder->guidtopropmaploc; mapitem; mapitem = mapitem->next) {
+ if (GUID_equal(guid, &mapitem->guid)) {
+ return mapitem;
+ }
+ }
+ return NULL;
+}
+
+static bool getbool(char *str)
+{
+ char *cpy = talloc_strdup(NULL, str);
+ bool result;
+
+ trim_string(cpy, " ", " ");
+ if (strequal("TRUE", cpy)) {
+ result = true;
+ } else {
+ result = false;
+ }
+ TALLOC_FREE(cpy);
+ return result;
+}
+
+struct {
+ const char* typename;
+ uint16_t type;
+} vtype_map[] = {
+ {"GUID", VT_CLSID},
+ {"String", VT_LPWSTR},
+ {"BString", VT_BSTR},
+ {"Double", VT_R8},
+ {"Buffer", VT_BLOB_OBJECT},
+ {"Byte", VT_UI1},
+ {"UInt64", VT_UI8},
+ {"Int64", VT_I8},
+ {"UInt32", VT_UI4},
+ {"Int32", VT_I4},
+ {"UInt16", VT_UI2},
+ {"Int16", VT_I2},
+ {"DateTime", VT_FILETIME},
+ {"Boolean", VT_BOOL}
+};
+
+static uint16_t getvtype(char *str, bool isvec)
+{
+ uint16_t result = UINT16_MAX;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(vtype_map); i++) {
+ if (strequal(vtype_map[i].typename, str)) {
+ result = vtype_map[i].type;
+ if (isvec) {
+ result |= VT_VECTOR;
+ }
+ break;
+ }
+ }
+ return result;
+}
+
+static bool parse_csv_line(TALLOC_CTX *ctx,
+ char **csvs, size_t num_values,
+ struct guidtopropmap_holder *propmap_holder)
+{
+ struct guidtopropmap *mapitem = NULL;
+ struct full_propset_info_list *item = NULL;
+
+ char *guid_str = NULL;
+ struct GUID guid;
+ bool ok;
+
+ item = talloc_zero(ctx,
+ struct full_propset_info_list);
+ if (!item) {
+ return false;
+ }
+
+ item->info.in_inverted_index = false;
+ item->info.is_column = true;
+ item->info.can_col_be_indexed = true;
+
+ if (strlen(csvs[1])) {
+ guid_str = talloc_strdup(ctx, csvs[1]);
+ }
+
+ if (!guid_str) {
+ DBG_ERR("out of memory\n");
+ return false;
+ }
+
+ if (!trim_string(guid_str, "{", "}")) {
+ return false;
+ }
+
+ if (strlen(csvs[0])) {
+ char *tmp = talloc_strdup(item, csvs[0]);
+ trim_string(tmp, " ", " ");
+ item->info.name = tmp;
+ }
+
+ if (strlen(csvs[2])) {
+ item->info.id = atoi(csvs[2]);
+ }
+
+ if (strlen(csvs[3])) {
+ item->info.in_inverted_index = getbool(csvs[3]);
+ }
+
+ if (strlen(csvs[4])) {
+ item->info.is_column = getbool(csvs[4]);
+ }
+
+ if (strlen(csvs[5])) {
+ item->info.can_col_be_indexed = getbool(csvs[5]);
+ }
+
+ if (strlen(csvs[6])) {
+ bool isvec = false;
+ uint16_t type;
+ if (strlen(csvs[0])) {
+ isvec = getbool(csvs[8]);
+ }
+ type = getvtype(csvs[6], isvec);
+ if (type == UINT16_MAX) {
+ DBG_ERR("failed to parse type\n");
+ return false;
+ }
+ item->info.vtype = type;
+ }
+
+ ok = parse_guid_string(guid_str, &guid);
+ if (!ok) {
+ return false;
+ }
+
+ mapitem = find_guid_props(propmap_holder, &guid);
+ if (!mapitem) {
+ mapitem = talloc_zero(propmap_holder,
+ struct guidtopropmap);
+ if (!mapitem) {
+ return false;
+ }
+ mapitem->guid = guid;
+ DLIST_ADD_END(propmap_holder->guidtopropmaploc, mapitem);
+ }
+
+ talloc_steal(mapitem, item);
+ DLIST_ADD_END(mapitem->propset, item);
+ return true;
+}
+
+static bool parse_properties_line(TALLOC_CTX *ctx,
+ const char* line,
+ struct guidtopropmap_holder *propmap_holder)
+{
+ int ret;
+ int pos;
+ char* strv = NULL;
+ char** csv_line = NULL;
+ char* t = NULL;
+ size_t len;
+
+ ret = strv_split(ctx,
+ &strv,
+ line,
+ ",");
+
+ if (ret != 0) {
+ DBG_ERR("failed to split line\n");
+ return false;
+ }
+
+ len = strv_count(strv);
+
+ if (len < 9) {
+ DBG_WARNING("skipping line as it doesn't have "
+ "enough fields\n");
+ return true;
+ }
+
+ csv_line = talloc_zero_array(ctx,
+ char *,
+ len);
+
+ if (!csv_line) {
+ DBG_ERR("out of memory\n");
+ return false;
+ }
+ for (pos = 0; pos < talloc_array_length(csv_line); pos++) {
+ t = strv_next(strv, t);
+ /* the scraped property file can have a non ascii char */
+ if (strlen(t) == 1 && *t == 0xa0) {
+ csv_line[pos] = talloc_strdup(csv_line,
+ "");
+ } else {
+ csv_line[pos] = talloc_strdup(csv_line,
+ t);
+ }
+ trim_string(csv_line[pos], " ", " ");
+ }
+
+ if (!parse_csv_line(csv_line, csv_line, len, propmap_holder)) {
+ DBG_ERR("failed to parse line\n");
+ TALLOC_FREE(csv_line);
+ return false;
+ }
+ TALLOC_FREE(csv_line);
+ return true;
+}
+
+static bool parse_properties_csvfile(TALLOC_CTX *ctx,
+ struct guidtopropmap_holder *propmap_holder,
+ const char* filename)
+{
+ char **lines = NULL;
+ int numlines;
+ int i;
+
+ if (filename == NULL || strlen(filename) == 0) {
+ return false;
+ }
+
+ lines = file_lines_load(filename,
+ &numlines,
+ BUFFER_SIZE,
+ ctx);
+ if (!lines) {
+ DBG_ERR("Failed to load %s\n", filename);
+ return false;
+ }
+ DBG_ERR("parsed %d lines\n", numlines);
+
+ for (i = 0; i < numlines; i++) {
+ TALLOC_CTX *line_ctx = talloc_init("line context");
+ if (!line_ctx) {
+ DBG_ERR("out of memory\n");
+ return false;
+ }
+
+ trim_string(lines[i], " ", " ");
+ if (lines[i][0] == '#') {
+ DBG_WARNING("skipping comment at line %d.\n)", i);
+ TALLOC_FREE(line_ctx);
+ continue;
+ }
+
+ if (!parse_properties_line(line_ctx,
+ lines[i],
+ propmap_holder)) {
+ DBG_ERR("Failed to parse line %d\n", i);
+ }
+ TALLOC_FREE(line_ctx);
+ }
+ return true;
+}
+
+static bool populate_map(struct guidtopropmap_holder *propmap_holder)
+{
+ const char * path = NULL;
+ path = lp_wsp_property_file();
+
+ /* first populate the map from property file */
+ if (path) {
+ parse_properties_csvfile(propmap_holder, propmap_holder, path);
+ }
+
+ return true;
+}
+
+static struct guidtopropmap_holder *propmap(void)
+{
+ static struct guidtopropmap_holder *holder = NULL;
+
+ if (!holder) {
+ holder = talloc_zero(NULL, struct guidtopropmap_holder);
+ if (holder) {
+ populate_map(holder);
+ }
+ }
+
+ return holder;
+}
+
+const struct full_propset_info *get_propset_info_with_guid(
+ const char *prop_name,
+ struct GUID *propset_guid)
+{
+ const struct full_propset_info *result = NULL;
+ struct guidtopropmap_holder *holder = NULL;
+ struct guidtopropmap *mapitem = NULL;
+
+ size_t i;
+ const struct full_guid_propset *guid_propset = NULL;
+
+ /* search builtin props first */
+ for (i = 0; full_propertyset[i].prop_info != NULL; i++) {
+ const struct full_propset_info *item = NULL;
+ guid_propset = &full_propertyset[i];
+ item = guid_propset->prop_info;
+ while (item->id) {
+ if (strequal(prop_name, item->name)) {
+ *propset_guid = guid_propset->guid;
+ result = item;
+ break;
+ }
+ item++;
+ }
+ if (result) {
+ break;
+ }
+ }
+
+ if (result) {
+ return result;
+ }
+
+ /* if we didn't find a match in builtin props try the extra props */
+ holder = propmap();
+ for (mapitem = holder->guidtopropmaploc; mapitem;
+ mapitem = mapitem->next) {
+ struct full_propset_info_list *propitem;
+ for (propitem = mapitem->propset; propitem;
+ propitem = propitem->next) {
+ if (strequal(prop_name, propitem->info.name)) {
+ *propset_guid = mapitem->guid;
+ result = &propitem->info;
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+const struct full_propset_info *get_prop_info(const char *prop_name)
+{
+ const struct full_propset_info *result = NULL;
+ struct GUID guid;
+ result = get_propset_info_with_guid(prop_name, &guid);
+ return result;
+}
+
+char *prop_from_fullprop(TALLOC_CTX *ctx, struct wsp_cfullpropspec *fullprop)
+{
+ size_t i;
+ char *result = NULL;
+ const struct full_propset_info *item = NULL;
+ const struct full_propset_info_list *prop_item = NULL;
+ bool search_by_id = (fullprop->ulkind == PRSPEC_PROPID);
+ struct guidtopropmap_holder *holder = NULL;
+ struct guidtopropmap *mapitem = NULL;
+
+ /* check builtin properties */
+ for (i = 0; full_propertyset[i].prop_info != NULL; i++) {
+ /* find propset */
+ if (GUID_equal(&fullprop->guidpropset,
+ &full_propertyset[i].guid)) {
+ item = full_propertyset[i].prop_info;
+ break;
+ }
+ }
+ if (item) {
+ while (item->id) {
+ if (search_by_id) {
+ if( fullprop->name_or_id.prspec == item->id) {
+ result = talloc_strdup(ctx, item->name);
+ break;
+ }
+ } else if (strcmp(item->name,
+ fullprop->name_or_id.propname.vstring)
+ == 0) {
+ result = talloc_strdup(ctx, item->name);
+ break;
+ }
+ item++;
+ }
+ }
+
+ /* not found, search the extra props */
+ if (!result) {
+ holder = propmap();
+
+ for (mapitem = holder->guidtopropmaploc; mapitem;
+ mapitem = mapitem->next) {
+ if (GUID_equal(&fullprop->guidpropset,
+ &mapitem->guid)) {
+ prop_item = mapitem->propset;
+ break;
+ }
+ }
+
+ for (;prop_item; prop_item = prop_item->next) {
+ if (search_by_id) {
+ if(fullprop->name_or_id.prspec ==
+ prop_item->info.id) {
+ result = talloc_strdup(ctx,
+ prop_item->info.name);
+ break;
+ }
+ } else if (strcmp(prop_item->info.name,
+ fullprop->name_or_id.propname.vstring) == 0) {
+ result = talloc_strdup(ctx,
+ prop_item->info.name);
+ break;
+ }
+ }
+ }
+
+ if (!result) {
+ result = GUID_string(ctx, &fullprop->guidpropset);
+
+ if (search_by_id) {
+ result = talloc_asprintf(result, "%s/%d", result,
+ fullprop->name_or_id.prspec);
+ } else {
+ result = talloc_asprintf(result, "%s/%s", result,
+ fullprop->name_or_id.propname.vstring);
+ }
+ }
+ return result;
+}
+
+const char *genmeth_to_string(uint32_t genmethod)
+{
+ const char *result = NULL;
+ switch (genmethod) {
+ case 0:
+ result = "equals";
+ break;
+ case 1:
+ result = "starts with";
+ break;
+ case 2:
+ result = "matches inflection";
+ break;
+ default:
+ result = NULL;
+ break;
+ }
+ return result;
+}
+
+bool is_operator(struct wsp_crestriction *restriction) {
+ bool result;
+ switch(restriction->ultype) {
+ case RTAND:
+ case RTOR:
+ case RTNOT:
+ result = true;
+ break;
+ default:
+ result = false;
+ break;
+ }
+ return result;
+}
+
+const char *op_as_string(struct wsp_crestriction *restriction)
+{
+ const char *op = NULL;
+ if (is_operator(restriction)) {
+ switch(restriction->ultype) {
+ case RTAND:
+ op = " && ";
+ break;
+ case RTOR:
+ op = " || ";
+ break;
+ case RTNOT:
+ op = "!";
+ break;
+ }
+ } else if (restriction->ultype == RTPROPERTY) {
+ struct wsp_cpropertyrestriction *prop_restr =
+ &restriction->restriction.cpropertyrestriction;
+ switch (prop_restr->relop & 0XF) {
+ case PREQ:
+ op = "=";
+ break;
+ case PRNE:
+ op = "!=";
+ break;
+ case PRGE:
+ op = ">=";
+ break;
+ case PRLE:
+ op = "<=";
+ break;
+ case PRLT:
+ op = "<";
+ break;
+ case PRGT:
+ op = ">";
+ break;
+ default:
+ break;
+ }
+ } else if (restriction->ultype == RTCONTENT) {
+ struct wsp_ccontentrestriction *content = NULL;
+ content = &restriction->restriction.ccontentrestriction;
+ op = genmeth_to_string(content->ulgeneratemethod);
+ } else if (restriction->ultype == RTNATLANGUAGE) {
+ op = "=";
+ }
+ return op;
+}
+
+struct wsp_cfullpropspec *get_full_prop(struct wsp_crestriction *restriction)
+{
+ struct wsp_cfullpropspec *result;
+ switch (restriction->ultype) {
+ case RTPROPERTY:
+ result = &restriction->restriction.cpropertyrestriction.property;
+ break;
+ case RTCONTENT:
+ result = &restriction->restriction.ccontentrestriction.property;
+ break;
+ case RTNATLANGUAGE:
+ result = &restriction->restriction.cnatlanguagerestriction.property;
+ break;
+ default:
+ result = NULL;
+ break;
+ }
+ return result;
+}
+
+const char *variant_as_string(TALLOC_CTX *ctx,
+ struct wsp_cbasestoragevariant *value, bool quote)
+{
+ const char* result = NULL;
+ switch(value->vtype) {
+ case VT_UI1:
+ result = talloc_asprintf(ctx, "%u",
+ value->vvalue.vt_ui1);
+ break;
+ case VT_INT:
+ case VT_I4:
+ result = talloc_asprintf(ctx, "%d",
+ value->vvalue.vt_i4);
+ break;
+ case VT_ERROR:
+ case VT_UINT:
+ case VT_UI4:
+ result = talloc_asprintf(ctx, "%u",
+ value->vvalue.vt_ui4);
+ break;
+ case VT_UI2:
+ case VT_I2:
+ result = talloc_asprintf(ctx, "%u",
+ value->vvalue.vt_ui2);
+ break;
+ case VT_BOOL:
+ result = talloc_asprintf(ctx, "%s",
+ value->vvalue.vt_ui2 == 0xFFFF ?
+ "true" : "false");
+ break;
+ case VT_DATE:
+ case VT_FILETIME: {
+ NTTIME filetime = value->vvalue.vt_ui8;
+ time_t unixtime;
+ struct tm *tm = NULL;
+ char datestring[256];
+ unixtime = nt_time_to_unix(filetime);
+ tm = gmtime(&unixtime);
+ strftime(datestring, sizeof(datestring), "%FT%TZ", tm);
+ result = talloc_strdup(ctx, datestring);
+ break;
+ }
+ case VT_R4: {
+ float f;
+ if (sizeof(f) != sizeof(value->vvalue.vt_ui4)) {
+ DBG_ERR("can't convert float\n");
+ break;
+ }
+ memcpy((void*)&f,
+ (void*)&value->vvalue.vt_ui4,
+ sizeof(value->vvalue.vt_ui4));
+ result = talloc_asprintf(ctx, "%f",
+ f);
+ break;
+ }
+ case VT_R8: {
+ /* should this really be unsigned ? */
+ double dval;
+ if (sizeof(dval) != sizeof(value->vvalue.vt_i8)) {
+ DBG_ERR("can't convert double\n");
+ break;
+ }
+ memcpy((void*)&dval,
+ (void*)&value->vvalue.vt_i8,
+ sizeof(dval));
+ result = talloc_asprintf(ctx, "%f",
+ dval);
+ break;
+ }
+ case VT_I8: {
+ result = talloc_asprintf(ctx, "%" PRIi64,
+ value->vvalue.vt_i8);
+ break;
+ }
+ case VT_UI8: {
+ result = talloc_asprintf(ctx, "%" PRIu64,
+ value->vvalue.vt_ui8);
+ break;
+ }
+ case VT_LPWSTR:
+ result = talloc_asprintf(ctx, "%s%s%s",
+ quote ? "\'" : "",
+ value->vvalue.vt_lpwstr.value,
+ quote ? "\'" : "");
+ break;
+ case VT_LPWSTR | VT_VECTOR: {
+ int num_elems =
+ value->vvalue.vt_lpwstr_v.vvector_elements;
+ int i;
+ for(i = 0; i < num_elems; i++) {
+ struct vt_lpwstr_vec *vec;
+ const char *val;
+ vec = &value->vvalue.vt_lpwstr_v;
+ val = vec->vvector_data[i].value;
+ result =
+ talloc_asprintf(ctx,
+ "%s%s%s%s%s",
+ result ? result : "",
+ i ? "," : "",
+ quote ? "\'" : "",
+ val,
+ quote ? "\'" : "");
+ }
+ break;
+ }
+ default:
+ DBG_INFO("can't represent unsupported vtype 0x%x as string\n",
+ value->vtype);
+ break;
+ }
+ return result;
+}
+
+static const struct {
+ uint32_t id;
+ const char *name;
+} typename_map[] = {
+ {VT_EMPTY, "Empty"},
+ {VT_NULL, "Null"},
+ {VT_I2, "VT_I2"},
+ {VT_I4, "VT_I4"},
+ {VT_I4, "VT_I4"},
+ {VT_R4, "VT_R4"},
+ {VT_R8, "VT_R8"},
+ {VT_CY, "VT_CY"},
+ {VT_DATE, "VT_DATE"},
+ {VT_BSTR, "VT_BSTR"},
+ {VT_I1, "VT_I1"},
+ {VT_UI1, "VT_UI1"},
+ {VT_UI2, "VT_UI2"},
+ {VT_UI4, "VT_UI4"},
+ {VT_I8, "VT_I8"},
+ {VT_UI8, "VT_UI8"},
+ {VT_INT, "VT_INT"},
+ {VT_UINT, "VT_UINT"},
+ {VT_ERROR, "VT_ERROR"},
+ {VT_BOOL, "VT_BOOL"},
+ {VT_VARIANT, "VT_VARIANT"},
+ {VT_DECIMAL, "VT_DECIMAL"},
+ {VT_FILETIME, "VT_FILETIME"},
+ {VT_BLOB, "VT_BLOB"},
+ {VT_BLOB_OBJECT, "VT_BLOB_OBJECT"},
+ {VT_CLSID, "VT_CLSID"},
+ {VT_LPSTR, "VT_LPSTR"},
+ {VT_LPWSTR, "VT_LPWSTR"},
+ {VT_COMPRESSED_LPWSTR, "VT_COMPRESSED_LPWSTR"},
+};
+
+const char *get_vtype_name(uint32_t type)
+{
+ const char *type_name = NULL;
+ static char result_buf[255];
+ int i;
+ uint32_t temp = type & ~(VT_VECTOR | VT_ARRAY);
+ for (i = 0; i < ARRAY_SIZE(typename_map); i++) {
+ if (temp == typename_map[i].id) {
+ type_name = typename_map[i].name;
+ break;
+ }
+ }
+ if (type & VT_VECTOR) {
+ snprintf(result_buf, sizeof(result_buf), "Vector | %s", type_name);
+ } else if (type & VT_ARRAY) {
+ snprintf(result_buf, sizeof(result_buf), "Array | %s", type_name);
+ } else {
+ snprintf(result_buf, sizeof(result_buf), "%s", type_name);
+ }
+ return result_buf;
+}
+
+bool is_variable_size(uint16_t vtype)
+{
+ bool result;
+ switch(vtype) {
+ case VT_LPWSTR:
+ case VT_COMPRESSED_LPWSTR:
+ case VT_BSTR:
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ case VT_VARIANT:
+ result = true;
+ break;
+ default:
+ result = false;
+ break;
+ }
+ return result;
+}
+
+const char *get_store_status(uint8_t status_byte)
+{
+ const char *result;
+ switch(status_byte) {
+ case 0:
+ result = "StoreStatusOk";
+ break;
+ case 1:
+ result = "StoreStatusDeferred";
+ break;
+ case 2:
+ result = "StoreStatusNull";
+ break;
+ default:
+ result = "Unknown Status";
+ break;
+ }
+ return result;
+}
+
+void set_variant_lpwstr(TALLOC_CTX *ctx,
+ struct wsp_cbasestoragevariant *vvalue,
+ const char *string_val)
+{
+ vvalue->vtype = VT_LPWSTR;
+ vvalue->vvalue.vt_lpwstr.value = talloc_strdup(ctx, string_val);
+}
+
+void set_variant_i4(TALLOC_CTX *ctx,
+ struct wsp_cbasestoragevariant *vvalue,
+ uint32_t val)
+{
+ vvalue->vtype = VT_I4;
+ vvalue->vvalue.vt_i4 = val;
+}
+
+void set_variant_vt_bool(TALLOC_CTX *ctx,
+ struct wsp_cbasestoragevariant *variant,
+ bool bval)
+{
+ variant->vtype = VT_BOOL;
+ variant->vvalue.vt_bool = bval;
+}
+
+static void fill_int32_vec(TALLOC_CTX* ctx,
+ int32_t **pdest,
+ int32_t* ivector, uint32_t elems)
+{
+ int i;
+ int32_t *dest = talloc_zero_array(ctx, int32_t, elems);
+ for ( i = 0; i < elems; i++ ) {
+ dest[ i ] = ivector[ i ];
+ }
+ *pdest = dest;
+}
+
+void set_variant_i4_vector(TALLOC_CTX *ctx,
+ struct wsp_cbasestoragevariant *variant,
+ int32_t* ivector, uint32_t elems)
+{
+ variant->vtype = VT_VECTOR | VT_I4;
+ variant->vvalue.vt_i4_vec.vvector_elements = elems;
+ fill_int32_vec(ctx, &variant->vvalue.vt_i4_vec.vvector_data, ivector, elems);
+}
+
+static void fill_string_vec(TALLOC_CTX* ctx,
+ struct wsp_cbasestoragevariant *variant,
+ const char **strings, uint16_t elems)
+{
+ int i;
+ variant->vvalue.vt_lpwstr_v.vvector_elements = elems;
+ variant->vvalue.vt_lpwstr_v.vvector_data = talloc_zero_array(ctx,
+ struct vt_lpwstr,
+ elems);
+
+ for( i = 0; i < elems; i++ ) {
+ variant->vvalue.vt_lpwstr_v.vvector_data[ i ].value = talloc_strdup(ctx, strings[ i ]);
+ }
+}
+
+static void fill_bstr_vec(TALLOC_CTX *ctx,
+ struct vt_bstr **pvector,
+ const char **strings, uint16_t elems)
+{
+ int i;
+ struct vt_bstr *vdata = talloc_zero_array(ctx, struct vt_bstr, elems);
+
+ for( i = 0; i < elems; i++ ) {
+ vdata [ i ].value = talloc_strdup(ctx, strings[ i ]);
+ }
+ *pvector = vdata;
+}
+
+void set_variant_bstr(TALLOC_CTX *ctx, struct wsp_cbasestoragevariant *variant,
+ const char *string_val)
+{
+ variant->vtype = VT_BSTR;
+ variant->vvalue.vt_bstr.value = talloc_strdup(ctx, string_val);
+}
+
+void set_variant_lpwstr_vector(TALLOC_CTX *ctx,
+ struct wsp_cbasestoragevariant *variant,
+ const char **string_vals, uint32_t elems)
+{
+ variant->vtype = VT_LPWSTR | VT_VECTOR;
+ fill_string_vec(ctx, variant, string_vals, elems);
+}
+
+void set_variant_array_bstr(TALLOC_CTX *ctx,
+ struct wsp_cbasestoragevariant *variant,
+ const char **string_vals, uint16_t elems)
+{
+ variant->vtype = VT_BSTR | VT_ARRAY;
+ variant->vvalue.vt_bstr_array.cdims = 1;
+ variant->vvalue.vt_bstr_array.ffeatures = 0;
+
+ variant->vvalue.vt_bstr_array.rgsabound =
+ talloc_zero_array(ctx, struct safearraybound, 1);
+
+ variant->vvalue.vt_bstr_array.rgsabound[0].celements = elems;
+ variant->vvalue.vt_bstr_array.rgsabound[0].ilbound = 0;
+ variant->vvalue.vt_bstr_array.cbelements = 0;
+ fill_bstr_vec(ctx, &variant->vvalue.vt_bstr_array.vdata,
+ string_vals, elems);
+ /*
+ * if cbelements is the num bytes per elem it kindof means each
+ * string in the array must be the same size ?
+ */
+
+ if (elems >0) {
+ variant->vvalue.vt_bstr_array.cbelements =
+ strlen_m_term(variant->vvalue.vt_bstr_array.vdata[0].value)*2;
+ }
+}
+
+/* create single dim array of vt_i4 */
+void set_variant_array_i4(TALLOC_CTX *ctx,
+ struct wsp_cbasestoragevariant *variant,
+ int32_t *vals, uint16_t elems)
+{
+ /* #TODO see if we can combine with other set_variant_array methods */
+ variant->vtype = VT_I4 | VT_ARRAY;
+ variant->vvalue.vt_i4_array.cdims = 1;
+ variant->vvalue.vt_i4_array.ffeatures = 0;
+
+ variant->vvalue.vt_i4_array.rgsabound =
+ talloc_zero_array(ctx, struct safearraybound, 1);
+
+ variant->vvalue.vt_i4_array.rgsabound[0].celements = elems;
+ variant->vvalue.vt_i4_array.rgsabound[0].ilbound = 0;
+ variant->vvalue.vt_i4_array.cbelements = sizeof(uint32_t);
+ fill_int32_vec(ctx, &variant->vvalue.vt_i4_array.vdata, vals, elems);
+}