python:tests: Use ‘False’ in boolean expression rather than ‘None’
[Samba.git] / librpc / wsp / wsp_util.c
blobfae6e0b2fe33b5088c737c8bae27a28cc3a5b518
1 /*
2 * Unix SMB/CIFS implementation.
4 * Window Search Service
6 * Copyright (c) Noel Power
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "librpc/wsp/wsp_util.h"
23 #include "librpc/gen_ndr/wsp.h"
24 #include "librpc/gen_ndr/ndr_wsp.h"
25 #include "lib/util/strv_util.h"
26 #include "lib/util/strv.h"
27 #include "lib/util/util_str_hex.h"
28 #include "source3/param/param_proto.h"
29 #include "lib/util/dlinklist.h"
31 #define BUFFER_SIZE 1024000
32 struct guidtopropmap_holder
34 struct guidtopropmap *guidtopropmaploc;
37 struct full_propset_info_list {
38 struct full_propset_info_list *prev, *next;
39 struct full_propset_info info;
42 struct guidtopropmap {
43 struct guidtopropmap *prev, *next;
44 struct GUID guid;
45 struct full_propset_info_list *propset;
48 static struct guidtopropmap *find_guid_props(
49 struct guidtopropmap_holder *holder,
50 const struct GUID *guid)
52 struct guidtopropmap *mapitem;
53 for (mapitem = holder->guidtopropmaploc; mapitem; mapitem = mapitem->next) {
54 if (GUID_equal(guid, &mapitem->guid)) {
55 return mapitem;
58 return NULL;
61 static bool getbool(char *str)
63 char *cpy = talloc_strdup(NULL, str);
64 bool result;
66 trim_string(cpy, " ", " ");
67 if (strequal("TRUE", cpy)) {
68 result = true;
69 } else {
70 result = false;
72 TALLOC_FREE(cpy);
73 return result;
76 struct {
77 const char* typename;
78 uint16_t type;
79 } vtype_map[] = {
80 {"GUID", VT_CLSID},
81 {"String", VT_LPWSTR},
82 {"BString", VT_BSTR},
83 {"Double", VT_R8},
84 {"Buffer", VT_BLOB_OBJECT},
85 {"Byte", VT_UI1},
86 {"UInt64", VT_UI8},
87 {"Int64", VT_I8},
88 {"UInt32", VT_UI4},
89 {"Int32", VT_I4},
90 {"UInt16", VT_UI2},
91 {"Int16", VT_I2},
92 {"DateTime", VT_FILETIME},
93 {"Boolean", VT_BOOL}
96 static uint16_t getvtype(char *str, bool isvec)
98 uint16_t result = UINT16_MAX;
99 int i;
100 for (i = 0; i < ARRAY_SIZE(vtype_map); i++) {
101 if (strequal(vtype_map[i].typename, str)) {
102 result = vtype_map[i].type;
103 if (isvec) {
104 result |= VT_VECTOR;
106 break;
109 return result;
112 static bool parse_csv_line(TALLOC_CTX *ctx,
113 char **csvs, size_t num_values,
114 struct guidtopropmap_holder *propmap_holder)
116 struct guidtopropmap *mapitem = NULL;
117 struct full_propset_info_list *item = NULL;
119 char *guid_str = NULL;
120 struct GUID guid;
121 bool ok;
123 item = talloc_zero(ctx,
124 struct full_propset_info_list);
125 if (!item) {
126 return false;
129 item->info.in_inverted_index = false;
130 item->info.is_column = true;
131 item->info.can_col_be_indexed = true;
133 if (strlen(csvs[1])) {
134 guid_str = talloc_strdup(ctx, csvs[1]);
137 if (!guid_str) {
138 DBG_ERR("out of memory\n");
139 return false;
142 if (!trim_string(guid_str, "{", "}")) {
143 return false;
146 if (strlen(csvs[0])) {
147 char *tmp = talloc_strdup(item, csvs[0]);
148 trim_string(tmp, " ", " ");
149 item->info.name = tmp;
152 if (strlen(csvs[2])) {
153 item->info.id = atoi(csvs[2]);
156 if (strlen(csvs[3])) {
157 item->info.in_inverted_index = getbool(csvs[3]);
160 if (strlen(csvs[4])) {
161 item->info.is_column = getbool(csvs[4]);
164 if (strlen(csvs[5])) {
165 item->info.can_col_be_indexed = getbool(csvs[5]);
168 if (strlen(csvs[6])) {
169 bool isvec = false;
170 uint16_t type;
171 if (strlen(csvs[0])) {
172 isvec = getbool(csvs[8]);
174 type = getvtype(csvs[6], isvec);
175 if (type == UINT16_MAX) {
176 DBG_ERR("failed to parse type\n");
177 return false;
179 item->info.vtype = type;
182 ok = parse_guid_string(guid_str, &guid);
183 if (!ok) {
184 return false;
187 mapitem = find_guid_props(propmap_holder, &guid);
188 if (!mapitem) {
189 mapitem = talloc_zero(propmap_holder,
190 struct guidtopropmap);
191 if (!mapitem) {
192 return false;
194 mapitem->guid = guid;
195 DLIST_ADD_END(propmap_holder->guidtopropmaploc, mapitem);
198 talloc_steal(mapitem, item);
199 DLIST_ADD_END(mapitem->propset, item);
200 return true;
203 static bool parse_properties_line(TALLOC_CTX *ctx,
204 const char* line,
205 struct guidtopropmap_holder *propmap_holder)
207 int ret;
208 int pos;
209 char* strv = NULL;
210 char** csv_line = NULL;
211 char* t = NULL;
212 size_t len;
214 ret = strv_split(ctx,
215 &strv,
216 line,
217 ",");
219 if (ret != 0) {
220 DBG_ERR("failed to split line\n");
221 return false;
224 len = strv_count(strv);
226 if (len < 9) {
227 DBG_WARNING("skipping line as it doesn't have "
228 "enough fields\n");
229 return true;
232 csv_line = talloc_zero_array(ctx,
233 char *,
234 len);
236 if (!csv_line) {
237 DBG_ERR("out of memory\n");
238 return false;
240 for (pos = 0; pos < talloc_array_length(csv_line); pos++) {
241 t = strv_next(strv, t);
242 /* the scraped property file can have a non ascii char */
243 if (strlen(t) == 1 && *t == 0xa0) {
244 csv_line[pos] = talloc_strdup(csv_line,
245 "");
246 } else {
247 csv_line[pos] = talloc_strdup(csv_line,
250 trim_string(csv_line[pos], " ", " ");
253 if (!parse_csv_line(csv_line, csv_line, len, propmap_holder)) {
254 DBG_ERR("failed to parse line\n");
255 TALLOC_FREE(csv_line);
256 return false;
258 TALLOC_FREE(csv_line);
259 return true;
262 static bool parse_properties_csvfile(TALLOC_CTX *ctx,
263 struct guidtopropmap_holder *propmap_holder,
264 const char* filename)
266 char **lines = NULL;
267 int numlines;
268 int i;
270 if (filename == NULL || strlen(filename) == 0) {
271 return false;
274 lines = file_lines_load(filename,
275 &numlines,
276 BUFFER_SIZE,
277 ctx);
278 if (!lines) {
279 DBG_ERR("Failed to load %s\n", filename);
280 return false;
282 DBG_ERR("parsed %d lines\n", numlines);
284 for (i = 0; i < numlines; i++) {
285 TALLOC_CTX *line_ctx = talloc_init("line context");
286 if (!line_ctx) {
287 DBG_ERR("out of memory\n");
288 return false;
291 trim_string(lines[i], " ", " ");
292 if (lines[i][0] == '#') {
293 DBG_WARNING("skipping comment at line %d.\n)", i);
294 TALLOC_FREE(line_ctx);
295 continue;
298 if (!parse_properties_line(line_ctx,
299 lines[i],
300 propmap_holder)) {
301 DBG_ERR("Failed to parse line %d\n", i);
303 TALLOC_FREE(line_ctx);
305 return true;
308 static bool populate_map(struct guidtopropmap_holder *propmap_holder)
310 const char * path = NULL;
311 path = lp_wsp_property_file();
313 /* first populate the map from property file */
314 if (path) {
315 parse_properties_csvfile(propmap_holder, propmap_holder, path);
318 return true;
321 static struct guidtopropmap_holder *propmap(void)
323 static struct guidtopropmap_holder *holder = NULL;
325 if (!holder) {
326 holder = talloc_zero(NULL, struct guidtopropmap_holder);
327 if (holder) {
328 populate_map(holder);
332 return holder;
335 const struct full_propset_info *get_propset_info_with_guid(
336 const char *prop_name,
337 struct GUID *propset_guid)
339 const struct full_propset_info *result = NULL;
340 struct guidtopropmap_holder *holder = NULL;
341 struct guidtopropmap *mapitem = NULL;
343 size_t i;
344 const struct full_guid_propset *guid_propset = NULL;
346 /* search builtin props first */
347 for (i = 0; full_propertyset[i].prop_info != NULL; i++) {
348 const struct full_propset_info *item = NULL;
349 guid_propset = &full_propertyset[i];
350 item = guid_propset->prop_info;
351 while (item->id) {
352 if (strequal(prop_name, item->name)) {
353 *propset_guid = guid_propset->guid;
354 result = item;
355 break;
357 item++;
359 if (result) {
360 break;
364 if (result) {
365 return result;
368 /* if we didn't find a match in builtin props try the extra props */
369 holder = propmap();
370 for (mapitem = holder->guidtopropmaploc; mapitem;
371 mapitem = mapitem->next) {
372 struct full_propset_info_list *propitem;
373 for (propitem = mapitem->propset; propitem;
374 propitem = propitem->next) {
375 if (strequal(prop_name, propitem->info.name)) {
376 *propset_guid = mapitem->guid;
377 result = &propitem->info;
378 break;
382 return result;
385 const struct full_propset_info *get_prop_info(const char *prop_name)
387 const struct full_propset_info *result = NULL;
388 struct GUID guid;
389 result = get_propset_info_with_guid(prop_name, &guid);
390 return result;
393 char *prop_from_fullprop(TALLOC_CTX *ctx, struct wsp_cfullpropspec *fullprop)
395 size_t i;
396 char *result = NULL;
397 const struct full_propset_info *item = NULL;
398 const struct full_propset_info_list *prop_item = NULL;
399 bool search_by_id = (fullprop->ulkind == PRSPEC_PROPID);
400 struct guidtopropmap_holder *holder = NULL;
401 struct guidtopropmap *mapitem = NULL;
403 /* check builtin properties */
404 for (i = 0; full_propertyset[i].prop_info != NULL; i++) {
405 /* find propset */
406 if (GUID_equal(&fullprop->guidpropset,
407 &full_propertyset[i].guid)) {
408 item = full_propertyset[i].prop_info;
409 break;
412 if (item) {
413 while (item->id) {
414 if (search_by_id) {
415 if( fullprop->name_or_id.prspec == item->id) {
416 result = talloc_strdup(ctx, item->name);
417 break;
419 } else if (strcmp(item->name,
420 fullprop->name_or_id.propname.vstring)
421 == 0) {
422 result = talloc_strdup(ctx, item->name);
423 break;
425 item++;
429 /* not found, search the extra props */
430 if (!result) {
431 holder = propmap();
433 for (mapitem = holder->guidtopropmaploc; mapitem;
434 mapitem = mapitem->next) {
435 if (GUID_equal(&fullprop->guidpropset,
436 &mapitem->guid)) {
437 prop_item = mapitem->propset;
438 break;
442 for (;prop_item; prop_item = prop_item->next) {
443 if (search_by_id) {
444 if(fullprop->name_or_id.prspec ==
445 prop_item->info.id) {
446 result = talloc_strdup(ctx,
447 prop_item->info.name);
448 break;
450 } else if (strcmp(prop_item->info.name,
451 fullprop->name_or_id.propname.vstring) == 0) {
452 result = talloc_strdup(ctx,
453 prop_item->info.name);
454 break;
459 if (!result) {
460 result = GUID_string(ctx, &fullprop->guidpropset);
462 if (search_by_id) {
463 result = talloc_asprintf(result, "%s/%d", result,
464 fullprop->name_or_id.prspec);
465 } else {
466 result = talloc_asprintf(result, "%s/%s", result,
467 fullprop->name_or_id.propname.vstring);
470 return result;
473 const char *genmeth_to_string(uint32_t genmethod)
475 const char *result = NULL;
476 switch (genmethod) {
477 case 0:
478 result = "equals";
479 break;
480 case 1:
481 result = "starts with";
482 break;
483 case 2:
484 result = "matches inflection";
485 break;
486 default:
487 result = NULL;
488 break;
490 return result;
493 bool is_operator(struct wsp_crestriction *restriction) {
494 bool result;
495 switch(restriction->ultype) {
496 case RTAND:
497 case RTOR:
498 case RTNOT:
499 result = true;
500 break;
501 default:
502 result = false;
503 break;
505 return result;
508 const char *op_as_string(struct wsp_crestriction *restriction)
510 const char *op = NULL;
511 if (is_operator(restriction)) {
512 switch(restriction->ultype) {
513 case RTAND:
514 op = " && ";
515 break;
516 case RTOR:
517 op = " || ";
518 break;
519 case RTNOT:
520 op = "!";
521 break;
523 } else if (restriction->ultype == RTPROPERTY) {
524 struct wsp_cpropertyrestriction *prop_restr =
525 &restriction->restriction.cpropertyrestriction;
526 switch (prop_restr->relop & 0XF) {
527 case PREQ:
528 op = "=";
529 break;
530 case PRNE:
531 op = "!=";
532 break;
533 case PRGE:
534 op = ">=";
535 break;
536 case PRLE:
537 op = "<=";
538 break;
539 case PRLT:
540 op = "<";
541 break;
542 case PRGT:
543 op = ">";
544 break;
545 default:
546 break;
548 } else if (restriction->ultype == RTCONTENT) {
549 struct wsp_ccontentrestriction *content = NULL;
550 content = &restriction->restriction.ccontentrestriction;
551 op = genmeth_to_string(content->ulgeneratemethod);
552 } else if (restriction->ultype == RTNATLANGUAGE) {
553 op = "=";
555 return op;
558 struct wsp_cfullpropspec *get_full_prop(struct wsp_crestriction *restriction)
560 struct wsp_cfullpropspec *result;
561 switch (restriction->ultype) {
562 case RTPROPERTY:
563 result = &restriction->restriction.cpropertyrestriction.property;
564 break;
565 case RTCONTENT:
566 result = &restriction->restriction.ccontentrestriction.property;
567 break;
568 case RTNATLANGUAGE:
569 result = &restriction->restriction.cnatlanguagerestriction.property;
570 break;
571 default:
572 result = NULL;
573 break;
575 return result;
578 const char *variant_as_string(TALLOC_CTX *ctx,
579 struct wsp_cbasestoragevariant *value, bool quote)
581 const char* result = NULL;
582 switch(value->vtype) {
583 case VT_UI1:
584 result = talloc_asprintf(ctx, "%u",
585 value->vvalue.vt_ui1);
586 break;
587 case VT_INT:
588 case VT_I4:
589 result = talloc_asprintf(ctx, "%d",
590 value->vvalue.vt_i4);
591 break;
592 case VT_ERROR:
593 case VT_UINT:
594 case VT_UI4:
595 result = talloc_asprintf(ctx, "%u",
596 value->vvalue.vt_ui4);
597 break;
598 case VT_UI2:
599 case VT_I2:
600 result = talloc_asprintf(ctx, "%u",
601 value->vvalue.vt_ui2);
602 break;
603 case VT_BOOL:
604 result = talloc_asprintf(ctx, "%s",
605 value->vvalue.vt_ui2 == 0xFFFF ?
606 "true" : "false");
607 break;
608 case VT_DATE:
609 case VT_FILETIME: {
610 NTTIME filetime = value->vvalue.vt_ui8;
611 time_t unixtime;
612 struct tm *tm = NULL;
613 char datestring[256];
614 unixtime = nt_time_to_unix(filetime);
615 tm = gmtime(&unixtime);
616 strftime(datestring, sizeof(datestring), "%FT%TZ", tm);
617 result = talloc_strdup(ctx, datestring);
618 break;
620 case VT_R4: {
621 float f;
622 if (sizeof(f) != sizeof(value->vvalue.vt_ui4)) {
623 DBG_ERR("can't convert float\n");
624 break;
626 memcpy((void*)&f,
627 (void*)&value->vvalue.vt_ui4,
628 sizeof(value->vvalue.vt_ui4));
629 result = talloc_asprintf(ctx, "%f",
631 break;
633 case VT_R8: {
634 /* should this really be unsigned ? */
635 double dval;
636 if (sizeof(dval) != sizeof(value->vvalue.vt_i8)) {
637 DBG_ERR("can't convert double\n");
638 break;
640 memcpy((void*)&dval,
641 (void*)&value->vvalue.vt_i8,
642 sizeof(dval));
643 result = talloc_asprintf(ctx, "%f",
644 dval);
645 break;
647 case VT_I8: {
648 result = talloc_asprintf(ctx, "%" PRIi64,
649 value->vvalue.vt_i8);
650 break;
652 case VT_UI8: {
653 result = talloc_asprintf(ctx, "%" PRIu64,
654 value->vvalue.vt_ui8);
655 break;
657 case VT_LPWSTR:
658 result = talloc_asprintf(ctx, "%s%s%s",
659 quote ? "\'" : "",
660 value->vvalue.vt_lpwstr.value,
661 quote ? "\'" : "");
662 break;
663 case VT_LPWSTR | VT_VECTOR: {
664 int num_elems =
665 value->vvalue.vt_lpwstr_v.vvector_elements;
666 int i;
667 for(i = 0; i < num_elems; i++) {
668 struct vt_lpwstr_vec *vec;
669 const char *val;
670 vec = &value->vvalue.vt_lpwstr_v;
671 val = vec->vvector_data[i].value;
672 result =
673 talloc_asprintf(ctx,
674 "%s%s%s%s%s",
675 result ? result : "",
676 i ? "," : "",
677 quote ? "\'" : "",
678 val,
679 quote ? "\'" : "");
681 break;
683 default:
684 DBG_INFO("can't represent unsupported vtype 0x%x as string\n",
685 value->vtype);
686 break;
688 return result;
691 static const struct {
692 uint32_t id;
693 const char *name;
694 } typename_map[] = {
695 {VT_EMPTY, "Empty"},
696 {VT_NULL, "Null"},
697 {VT_I2, "VT_I2"},
698 {VT_I4, "VT_I4"},
699 {VT_I4, "VT_I4"},
700 {VT_R4, "VT_R4"},
701 {VT_R8, "VT_R8"},
702 {VT_CY, "VT_CY"},
703 {VT_DATE, "VT_DATE"},
704 {VT_BSTR, "VT_BSTR"},
705 {VT_I1, "VT_I1"},
706 {VT_UI1, "VT_UI1"},
707 {VT_UI2, "VT_UI2"},
708 {VT_UI4, "VT_UI4"},
709 {VT_I8, "VT_I8"},
710 {VT_UI8, "VT_UI8"},
711 {VT_INT, "VT_INT"},
712 {VT_UINT, "VT_UINT"},
713 {VT_ERROR, "VT_ERROR"},
714 {VT_BOOL, "VT_BOOL"},
715 {VT_VARIANT, "VT_VARIANT"},
716 {VT_DECIMAL, "VT_DECIMAL"},
717 {VT_FILETIME, "VT_FILETIME"},
718 {VT_BLOB, "VT_BLOB"},
719 {VT_BLOB_OBJECT, "VT_BLOB_OBJECT"},
720 {VT_CLSID, "VT_CLSID"},
721 {VT_LPSTR, "VT_LPSTR"},
722 {VT_LPWSTR, "VT_LPWSTR"},
723 {VT_COMPRESSED_LPWSTR, "VT_COMPRESSED_LPWSTR"},
726 const char *get_vtype_name(uint32_t type)
728 const char *type_name = NULL;
729 static char result_buf[255];
730 int i;
731 uint32_t temp = type & ~(VT_VECTOR | VT_ARRAY);
732 for (i = 0; i < ARRAY_SIZE(typename_map); i++) {
733 if (temp == typename_map[i].id) {
734 type_name = typename_map[i].name;
735 break;
738 if (type & VT_VECTOR) {
739 snprintf(result_buf, sizeof(result_buf), "Vector | %s", type_name);
740 } else if (type & VT_ARRAY) {
741 snprintf(result_buf, sizeof(result_buf), "Array | %s", type_name);
742 } else {
743 snprintf(result_buf, sizeof(result_buf), "%s", type_name);
745 return result_buf;
748 bool is_variable_size(uint16_t vtype)
750 bool result;
751 switch(vtype) {
752 case VT_LPWSTR:
753 case VT_COMPRESSED_LPWSTR:
754 case VT_BSTR:
755 case VT_BLOB:
756 case VT_BLOB_OBJECT:
757 case VT_VARIANT:
758 result = true;
759 break;
760 default:
761 result = false;
762 break;
764 return result;
767 const char *get_store_status(uint8_t status_byte)
769 const char *result;
770 switch(status_byte) {
771 case 0:
772 result = "StoreStatusOk";
773 break;
774 case 1:
775 result = "StoreStatusDeferred";
776 break;
777 case 2:
778 result = "StoreStatusNull";
779 break;
780 default:
781 result = "Unknown Status";
782 break;
784 return result;
787 void set_variant_lpwstr(TALLOC_CTX *ctx,
788 struct wsp_cbasestoragevariant *vvalue,
789 const char *string_val)
791 vvalue->vtype = VT_LPWSTR;
792 vvalue->vvalue.vt_lpwstr.value = talloc_strdup(ctx, string_val);
795 void set_variant_i4(TALLOC_CTX *ctx,
796 struct wsp_cbasestoragevariant *vvalue,
797 uint32_t val)
799 vvalue->vtype = VT_I4;
800 vvalue->vvalue.vt_i4 = val;
803 void set_variant_vt_bool(TALLOC_CTX *ctx,
804 struct wsp_cbasestoragevariant *variant,
805 bool bval)
807 variant->vtype = VT_BOOL;
808 variant->vvalue.vt_bool = bval;
811 static void fill_int32_vec(TALLOC_CTX* ctx,
812 int32_t **pdest,
813 int32_t* ivector, uint32_t elems)
815 int i;
816 int32_t *dest = talloc_zero_array(ctx, int32_t, elems);
817 for ( i = 0; i < elems; i++ ) {
818 dest[ i ] = ivector[ i ];
820 *pdest = dest;
823 void set_variant_i4_vector(TALLOC_CTX *ctx,
824 struct wsp_cbasestoragevariant *variant,
825 int32_t* ivector, uint32_t elems)
827 variant->vtype = VT_VECTOR | VT_I4;
828 variant->vvalue.vt_i4_vec.vvector_elements = elems;
829 fill_int32_vec(ctx, &variant->vvalue.vt_i4_vec.vvector_data, ivector, elems);
832 static void fill_string_vec(TALLOC_CTX* ctx,
833 struct wsp_cbasestoragevariant *variant,
834 const char **strings, uint16_t elems)
836 int i;
837 variant->vvalue.vt_lpwstr_v.vvector_elements = elems;
838 variant->vvalue.vt_lpwstr_v.vvector_data = talloc_zero_array(ctx,
839 struct vt_lpwstr,
840 elems);
842 for( i = 0; i < elems; i++ ) {
843 variant->vvalue.vt_lpwstr_v.vvector_data[ i ].value = talloc_strdup(ctx, strings[ i ]);
847 static void fill_bstr_vec(TALLOC_CTX *ctx,
848 struct vt_bstr **pvector,
849 const char **strings, uint16_t elems)
851 int i;
852 struct vt_bstr *vdata = talloc_zero_array(ctx, struct vt_bstr, elems);
854 for( i = 0; i < elems; i++ ) {
855 vdata [ i ].value = talloc_strdup(ctx, strings[ i ]);
857 *pvector = vdata;
860 void set_variant_bstr(TALLOC_CTX *ctx, struct wsp_cbasestoragevariant *variant,
861 const char *string_val)
863 variant->vtype = VT_BSTR;
864 variant->vvalue.vt_bstr.value = talloc_strdup(ctx, string_val);
867 void set_variant_lpwstr_vector(TALLOC_CTX *ctx,
868 struct wsp_cbasestoragevariant *variant,
869 const char **string_vals, uint32_t elems)
871 variant->vtype = VT_LPWSTR | VT_VECTOR;
872 fill_string_vec(ctx, variant, string_vals, elems);
875 void set_variant_array_bstr(TALLOC_CTX *ctx,
876 struct wsp_cbasestoragevariant *variant,
877 const char **string_vals, uint16_t elems)
879 variant->vtype = VT_BSTR | VT_ARRAY;
880 variant->vvalue.vt_bstr_array.cdims = 1;
881 variant->vvalue.vt_bstr_array.ffeatures = 0;
883 variant->vvalue.vt_bstr_array.rgsabound =
884 talloc_zero_array(ctx, struct safearraybound, 1);
886 variant->vvalue.vt_bstr_array.rgsabound[0].celements = elems;
887 variant->vvalue.vt_bstr_array.rgsabound[0].ilbound = 0;
888 variant->vvalue.vt_bstr_array.cbelements = 0;
889 fill_bstr_vec(ctx, &variant->vvalue.vt_bstr_array.vdata,
890 string_vals, elems);
892 * if cbelements is the num bytes per elem it kindof means each
893 * string in the array must be the same size ?
896 if (elems >0) {
897 variant->vvalue.vt_bstr_array.cbelements =
898 strlen_m_term(variant->vvalue.vt_bstr_array.vdata[0].value)*2;
902 /* create single dim array of vt_i4 */
903 void set_variant_array_i4(TALLOC_CTX *ctx,
904 struct wsp_cbasestoragevariant *variant,
905 int32_t *vals, uint16_t elems)
907 /* #TODO see if we can combine with other set_variant_array methods */
908 variant->vtype = VT_I4 | VT_ARRAY;
909 variant->vvalue.vt_i4_array.cdims = 1;
910 variant->vvalue.vt_i4_array.ffeatures = 0;
912 variant->vvalue.vt_i4_array.rgsabound =
913 talloc_zero_array(ctx, struct safearraybound, 1);
915 variant->vvalue.vt_i4_array.rgsabound[0].celements = elems;
916 variant->vvalue.vt_i4_array.rgsabound[0].ilbound = 0;
917 variant->vvalue.vt_i4_array.cbelements = sizeof(uint32_t);
918 fill_int32_vec(ctx, &variant->vvalue.vt_i4_array.vdata, vals, elems);