pylibsmb: Return reparse_tag from directory listing
[Samba.git] / librpc / wsp / wsp_util.c
blobd07338b1b5abb218be164874c622d1c599f0ee1c
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 "lib/util/util_file.h"
23 #include "librpc/wsp/wsp_util.h"
24 #include "librpc/gen_ndr/wsp.h"
25 #include "librpc/gen_ndr/ndr_wsp.h"
26 #include "lib/util/strv_util.h"
27 #include "lib/util/strv.h"
28 #include "lib/util/util_str_hex.h"
29 #include "source3/param/param_proto.h"
30 #include "lib/util/dlinklist.h"
32 #define BUFFER_SIZE 1024000
33 struct guidtopropmap_holder
35 struct guidtopropmap *guidtopropmaploc;
38 struct full_propset_info_list {
39 struct full_propset_info_list *prev, *next;
40 struct full_propset_info info;
43 struct guidtopropmap {
44 struct guidtopropmap *prev, *next;
45 struct GUID guid;
46 struct full_propset_info_list *propset;
49 static struct guidtopropmap *find_guid_props(
50 struct guidtopropmap_holder *holder,
51 const struct GUID *guid)
53 struct guidtopropmap *mapitem;
54 for (mapitem = holder->guidtopropmaploc; mapitem; mapitem = mapitem->next) {
55 if (GUID_equal(guid, &mapitem->guid)) {
56 return mapitem;
59 return NULL;
62 static bool getbool(char *str)
64 char *cpy = talloc_strdup(NULL, str);
65 bool result;
67 trim_string(cpy, " ", " ");
68 if (strequal("TRUE", cpy)) {
69 result = true;
70 } else {
71 result = false;
73 TALLOC_FREE(cpy);
74 return result;
77 struct {
78 const char* typename;
79 uint16_t type;
80 } vtype_map[] = {
81 {"GUID", VT_CLSID},
82 {"String", VT_LPWSTR},
83 {"BString", VT_BSTR},
84 {"Double", VT_R8},
85 {"Buffer", VT_BLOB_OBJECT},
86 {"Byte", VT_UI1},
87 {"UInt64", VT_UI8},
88 {"Int64", VT_I8},
89 {"UInt32", VT_UI4},
90 {"Int32", VT_I4},
91 {"UInt16", VT_UI2},
92 {"Int16", VT_I2},
93 {"DateTime", VT_FILETIME},
94 {"Boolean", VT_BOOL}
97 static uint16_t getvtype(char *str, bool isvec)
99 uint16_t result = UINT16_MAX;
100 int i;
101 for (i = 0; i < ARRAY_SIZE(vtype_map); i++) {
102 if (strequal(vtype_map[i].typename, str)) {
103 result = vtype_map[i].type;
104 if (isvec) {
105 result |= VT_VECTOR;
107 break;
110 return result;
113 static bool parse_csv_line(TALLOC_CTX *ctx,
114 char **csvs, size_t num_values,
115 struct guidtopropmap_holder *propmap_holder)
117 struct guidtopropmap *mapitem = NULL;
118 struct full_propset_info_list *item = NULL;
120 char *guid_str = NULL;
121 struct GUID guid;
122 bool ok;
124 item = talloc_zero(ctx,
125 struct full_propset_info_list);
126 if (!item) {
127 return false;
130 item->info.in_inverted_index = false;
131 item->info.is_column = true;
132 item->info.can_col_be_indexed = true;
134 if (strlen(csvs[1])) {
135 guid_str = talloc_strdup(ctx, csvs[1]);
138 if (!guid_str) {
139 DBG_ERR("out of memory\n");
140 return false;
143 if (!trim_string(guid_str, "{", "}")) {
144 return false;
147 if (strlen(csvs[0])) {
148 char *tmp = talloc_strdup(item, csvs[0]);
149 trim_string(tmp, " ", " ");
150 item->info.name = tmp;
153 if (strlen(csvs[2])) {
154 item->info.id = atoi(csvs[2]);
157 if (strlen(csvs[3])) {
158 item->info.in_inverted_index = getbool(csvs[3]);
161 if (strlen(csvs[4])) {
162 item->info.is_column = getbool(csvs[4]);
165 if (strlen(csvs[5])) {
166 item->info.can_col_be_indexed = getbool(csvs[5]);
169 if (strlen(csvs[6])) {
170 bool isvec = false;
171 uint16_t type;
172 if (strlen(csvs[0])) {
173 isvec = getbool(csvs[8]);
175 type = getvtype(csvs[6], isvec);
176 if (type == UINT16_MAX) {
177 DBG_ERR("failed to parse type\n");
178 return false;
180 item->info.vtype = type;
183 ok = parse_guid_string(guid_str, &guid);
184 if (!ok) {
185 return false;
188 mapitem = find_guid_props(propmap_holder, &guid);
189 if (!mapitem) {
190 mapitem = talloc_zero(propmap_holder,
191 struct guidtopropmap);
192 if (!mapitem) {
193 return false;
195 mapitem->guid = guid;
196 DLIST_ADD_END(propmap_holder->guidtopropmaploc, mapitem);
199 talloc_steal(mapitem, item);
200 DLIST_ADD_END(mapitem->propset, item);
201 return true;
204 static bool parse_properties_line(TALLOC_CTX *ctx,
205 const char* line,
206 struct guidtopropmap_holder *propmap_holder)
208 int ret;
209 int pos;
210 char* strv = NULL;
211 char** csv_line = NULL;
212 char* t = NULL;
213 size_t len;
215 ret = strv_split(ctx,
216 &strv,
217 line,
218 ",");
220 if (ret != 0) {
221 DBG_ERR("failed to split line\n");
222 return false;
225 len = strv_count(strv);
227 if (len < 9) {
228 DBG_WARNING("skipping line as it doesn't have "
229 "enough fields\n");
230 return true;
233 csv_line = talloc_zero_array(ctx,
234 char *,
235 len);
237 if (!csv_line) {
238 DBG_ERR("out of memory\n");
239 return false;
241 for (pos = 0; pos < talloc_array_length(csv_line); pos++) {
242 t = strv_next(strv, t);
243 /* the scraped property file can have a non ascii char */
244 if (strlen(t) == 1 && *t == 0xa0) {
245 csv_line[pos] = talloc_strdup(csv_line,
246 "");
247 } else {
248 csv_line[pos] = talloc_strdup(csv_line,
251 trim_string(csv_line[pos], " ", " ");
254 if (!parse_csv_line(csv_line, csv_line, len, propmap_holder)) {
255 DBG_ERR("failed to parse line\n");
256 TALLOC_FREE(csv_line);
257 return false;
259 TALLOC_FREE(csv_line);
260 return true;
263 static bool parse_properties_csvfile(TALLOC_CTX *ctx,
264 struct guidtopropmap_holder *propmap_holder,
265 const char* filename)
267 char **lines = NULL;
268 int numlines;
269 int i;
271 if (filename == NULL || strlen(filename) == 0) {
272 return false;
275 lines = file_lines_load(filename,
276 &numlines,
277 BUFFER_SIZE,
278 ctx);
279 if (!lines) {
280 DBG_ERR("Failed to load %s\n", filename);
281 return false;
283 DBG_ERR("parsed %d lines\n", numlines);
285 for (i = 0; i < numlines; i++) {
286 TALLOC_CTX *line_ctx = talloc_init("line context");
287 if (!line_ctx) {
288 DBG_ERR("out of memory\n");
289 return false;
292 trim_string(lines[i], " ", " ");
293 if (lines[i][0] == '#') {
294 DBG_WARNING("skipping comment at line %d.\n)", i);
295 TALLOC_FREE(line_ctx);
296 continue;
299 if (!parse_properties_line(line_ctx,
300 lines[i],
301 propmap_holder)) {
302 DBG_ERR("Failed to parse line %d\n", i);
304 TALLOC_FREE(line_ctx);
306 return true;
309 static bool populate_map(struct guidtopropmap_holder *propmap_holder)
311 const char * path = NULL;
312 path = lp_wsp_property_file();
314 /* first populate the map from property file */
315 if (path) {
316 parse_properties_csvfile(propmap_holder, propmap_holder, path);
319 return true;
322 static struct guidtopropmap_holder *propmap(void)
324 static struct guidtopropmap_holder *holder = NULL;
326 if (!holder) {
327 holder = talloc_zero(NULL, struct guidtopropmap_holder);
328 if (holder) {
329 populate_map(holder);
333 return holder;
336 const struct full_propset_info *get_propset_info_with_guid(
337 const char *prop_name,
338 struct GUID *propset_guid)
340 const struct full_propset_info *result = NULL;
341 struct guidtopropmap_holder *holder = NULL;
342 struct guidtopropmap *mapitem = NULL;
344 size_t i;
345 const struct full_guid_propset *guid_propset = NULL;
347 /* search builtin props first */
348 for (i = 0; full_propertyset[i].prop_info != NULL; i++) {
349 const struct full_propset_info *item = NULL;
350 guid_propset = &full_propertyset[i];
351 item = guid_propset->prop_info;
352 while (item->id) {
353 if (strequal(prop_name, item->name)) {
354 *propset_guid = guid_propset->guid;
355 result = item;
356 break;
358 item++;
360 if (result) {
361 break;
365 if (result) {
366 return result;
369 /* if we didn't find a match in builtin props try the extra props */
370 holder = propmap();
371 for (mapitem = holder->guidtopropmaploc; mapitem;
372 mapitem = mapitem->next) {
373 struct full_propset_info_list *propitem;
374 for (propitem = mapitem->propset; propitem;
375 propitem = propitem->next) {
376 if (strequal(prop_name, propitem->info.name)) {
377 *propset_guid = mapitem->guid;
378 result = &propitem->info;
379 break;
383 return result;
386 const struct full_propset_info *get_prop_info(const char *prop_name)
388 const struct full_propset_info *result = NULL;
389 struct GUID guid;
390 result = get_propset_info_with_guid(prop_name, &guid);
391 return result;
394 char *prop_from_fullprop(TALLOC_CTX *ctx, struct wsp_cfullpropspec *fullprop)
396 size_t i;
397 char *result = NULL;
398 const struct full_propset_info *item = NULL;
399 const struct full_propset_info_list *prop_item = NULL;
400 bool search_by_id = (fullprop->ulkind == PRSPEC_PROPID);
401 struct guidtopropmap_holder *holder = NULL;
402 struct guidtopropmap *mapitem = NULL;
404 /* check builtin properties */
405 for (i = 0; full_propertyset[i].prop_info != NULL; i++) {
406 /* find propset */
407 if (GUID_equal(&fullprop->guidpropset,
408 &full_propertyset[i].guid)) {
409 item = full_propertyset[i].prop_info;
410 break;
413 if (item) {
414 while (item->id) {
415 if (search_by_id) {
416 if( fullprop->name_or_id.prspec == item->id) {
417 result = talloc_strdup(ctx, item->name);
418 break;
420 } else if (strcmp(item->name,
421 fullprop->name_or_id.propname.vstring)
422 == 0) {
423 result = talloc_strdup(ctx, item->name);
424 break;
426 item++;
430 /* not found, search the extra props */
431 if (!result) {
432 holder = propmap();
434 for (mapitem = holder->guidtopropmaploc; mapitem;
435 mapitem = mapitem->next) {
436 if (GUID_equal(&fullprop->guidpropset,
437 &mapitem->guid)) {
438 prop_item = mapitem->propset;
439 break;
443 for (;prop_item; prop_item = prop_item->next) {
444 if (search_by_id) {
445 if(fullprop->name_or_id.prspec ==
446 prop_item->info.id) {
447 result = talloc_strdup(ctx,
448 prop_item->info.name);
449 break;
451 } else if (strcmp(prop_item->info.name,
452 fullprop->name_or_id.propname.vstring) == 0) {
453 result = talloc_strdup(ctx,
454 prop_item->info.name);
455 break;
460 if (!result) {
461 result = GUID_string(ctx, &fullprop->guidpropset);
463 if (search_by_id) {
464 result = talloc_asprintf(result, "%s/%d", result,
465 fullprop->name_or_id.prspec);
466 } else {
467 result = talloc_asprintf(result, "%s/%s", result,
468 fullprop->name_or_id.propname.vstring);
471 return result;
474 const char *genmeth_to_string(uint32_t genmethod)
476 const char *result = NULL;
477 switch (genmethod) {
478 case 0:
479 result = "equals";
480 break;
481 case 1:
482 result = "starts with";
483 break;
484 case 2:
485 result = "matches inflection";
486 break;
487 default:
488 result = NULL;
489 break;
491 return result;
494 bool is_operator(struct wsp_crestriction *restriction) {
495 bool result;
496 switch(restriction->ultype) {
497 case RTAND:
498 case RTOR:
499 case RTNOT:
500 result = true;
501 break;
502 default:
503 result = false;
504 break;
506 return result;
509 const char *op_as_string(struct wsp_crestriction *restriction)
511 const char *op = NULL;
512 if (is_operator(restriction)) {
513 switch(restriction->ultype) {
514 case RTAND:
515 op = " && ";
516 break;
517 case RTOR:
518 op = " || ";
519 break;
520 case RTNOT:
521 op = "!";
522 break;
524 } else if (restriction->ultype == RTPROPERTY) {
525 struct wsp_cpropertyrestriction *prop_restr =
526 &restriction->restriction.cpropertyrestriction;
527 switch (prop_restr->relop & 0XF) {
528 case PREQ:
529 op = "=";
530 break;
531 case PRNE:
532 op = "!=";
533 break;
534 case PRGE:
535 op = ">=";
536 break;
537 case PRLE:
538 op = "<=";
539 break;
540 case PRLT:
541 op = "<";
542 break;
543 case PRGT:
544 op = ">";
545 break;
546 default:
547 break;
549 } else if (restriction->ultype == RTCONTENT) {
550 struct wsp_ccontentrestriction *content = NULL;
551 content = &restriction->restriction.ccontentrestriction;
552 op = genmeth_to_string(content->ulgeneratemethod);
553 } else if (restriction->ultype == RTNATLANGUAGE) {
554 op = "=";
556 return op;
559 struct wsp_cfullpropspec *get_full_prop(struct wsp_crestriction *restriction)
561 struct wsp_cfullpropspec *result;
562 switch (restriction->ultype) {
563 case RTPROPERTY:
564 result = &restriction->restriction.cpropertyrestriction.property;
565 break;
566 case RTCONTENT:
567 result = &restriction->restriction.ccontentrestriction.property;
568 break;
569 case RTNATLANGUAGE:
570 result = &restriction->restriction.cnatlanguagerestriction.property;
571 break;
572 default:
573 result = NULL;
574 break;
576 return result;
579 const char *variant_as_string(TALLOC_CTX *ctx,
580 struct wsp_cbasestoragevariant *value, bool quote)
582 const char* result = NULL;
583 switch(value->vtype) {
584 case VT_UI1:
585 result = talloc_asprintf(ctx, "%u",
586 value->vvalue.vt_ui1);
587 break;
588 case VT_INT:
589 case VT_I4:
590 result = talloc_asprintf(ctx, "%d",
591 value->vvalue.vt_i4);
592 break;
593 case VT_ERROR:
594 case VT_UINT:
595 case VT_UI4:
596 result = talloc_asprintf(ctx, "%u",
597 value->vvalue.vt_ui4);
598 break;
599 case VT_UI2:
600 case VT_I2:
601 result = talloc_asprintf(ctx, "%u",
602 value->vvalue.vt_ui2);
603 break;
604 case VT_BOOL:
605 result = talloc_asprintf(ctx, "%s",
606 value->vvalue.vt_ui2 == 0xFFFF ?
607 "true" : "false");
608 break;
609 case VT_DATE:
610 case VT_FILETIME: {
611 NTTIME filetime = value->vvalue.vt_ui8;
612 time_t unixtime;
613 struct tm *tm = NULL;
614 char datestring[256];
615 unixtime = nt_time_to_unix(filetime);
616 tm = gmtime(&unixtime);
617 strftime(datestring, sizeof(datestring), "%FT%TZ", tm);
618 result = talloc_strdup(ctx, datestring);
619 break;
621 case VT_R4: {
622 float f;
623 if (sizeof(f) != sizeof(value->vvalue.vt_ui4)) {
624 DBG_ERR("can't convert float\n");
625 break;
627 memcpy((void*)&f,
628 (void*)&value->vvalue.vt_ui4,
629 sizeof(value->vvalue.vt_ui4));
630 result = talloc_asprintf(ctx, "%f",
632 break;
634 case VT_R8: {
635 /* should this really be unsigned ? */
636 double dval;
637 if (sizeof(dval) != sizeof(value->vvalue.vt_i8)) {
638 DBG_ERR("can't convert double\n");
639 break;
641 memcpy((void*)&dval,
642 (void*)&value->vvalue.vt_i8,
643 sizeof(dval));
644 result = talloc_asprintf(ctx, "%f",
645 dval);
646 break;
648 case VT_I8: {
649 result = talloc_asprintf(ctx, "%" PRIi64,
650 value->vvalue.vt_i8);
651 break;
653 case VT_UI8: {
654 result = talloc_asprintf(ctx, "%" PRIu64,
655 value->vvalue.vt_ui8);
656 break;
658 case VT_LPWSTR:
659 result = talloc_asprintf(ctx, "%s%s%s",
660 quote ? "\'" : "",
661 value->vvalue.vt_lpwstr.value,
662 quote ? "\'" : "");
663 break;
664 case VT_LPWSTR | VT_VECTOR: {
665 int num_elems =
666 value->vvalue.vt_lpwstr_v.vvector_elements;
667 int i;
668 for(i = 0; i < num_elems; i++) {
669 struct vt_lpwstr_vec *vec;
670 const char *val;
671 vec = &value->vvalue.vt_lpwstr_v;
672 val = vec->vvector_data[i].value;
673 result =
674 talloc_asprintf(ctx,
675 "%s%s%s%s%s",
676 result ? result : "",
677 i ? "," : "",
678 quote ? "\'" : "",
679 val,
680 quote ? "\'" : "");
682 break;
684 default:
685 DBG_INFO("can't represent unsupported vtype 0x%x as string\n",
686 value->vtype);
687 break;
689 return result;
692 static const struct {
693 uint32_t id;
694 const char *name;
695 } typename_map[] = {
696 {VT_EMPTY, "Empty"},
697 {VT_NULL, "Null"},
698 {VT_I2, "VT_I2"},
699 {VT_I4, "VT_I4"},
700 {VT_I4, "VT_I4"},
701 {VT_R4, "VT_R4"},
702 {VT_R8, "VT_R8"},
703 {VT_CY, "VT_CY"},
704 {VT_DATE, "VT_DATE"},
705 {VT_BSTR, "VT_BSTR"},
706 {VT_I1, "VT_I1"},
707 {VT_UI1, "VT_UI1"},
708 {VT_UI2, "VT_UI2"},
709 {VT_UI4, "VT_UI4"},
710 {VT_I8, "VT_I8"},
711 {VT_UI8, "VT_UI8"},
712 {VT_INT, "VT_INT"},
713 {VT_UINT, "VT_UINT"},
714 {VT_ERROR, "VT_ERROR"},
715 {VT_BOOL, "VT_BOOL"},
716 {VT_VARIANT, "VT_VARIANT"},
717 {VT_DECIMAL, "VT_DECIMAL"},
718 {VT_FILETIME, "VT_FILETIME"},
719 {VT_BLOB, "VT_BLOB"},
720 {VT_BLOB_OBJECT, "VT_BLOB_OBJECT"},
721 {VT_CLSID, "VT_CLSID"},
722 {VT_LPSTR, "VT_LPSTR"},
723 {VT_LPWSTR, "VT_LPWSTR"},
724 {VT_COMPRESSED_LPWSTR, "VT_COMPRESSED_LPWSTR"},
727 const char *get_vtype_name(uint32_t type)
729 const char *type_name = NULL;
730 static char result_buf[255];
731 int i;
732 uint32_t temp = type & ~(VT_VECTOR | VT_ARRAY);
733 for (i = 0; i < ARRAY_SIZE(typename_map); i++) {
734 if (temp == typename_map[i].id) {
735 type_name = typename_map[i].name;
736 break;
739 if (type & VT_VECTOR) {
740 snprintf(result_buf, sizeof(result_buf), "Vector | %s", type_name);
741 } else if (type & VT_ARRAY) {
742 snprintf(result_buf, sizeof(result_buf), "Array | %s", type_name);
743 } else {
744 snprintf(result_buf, sizeof(result_buf), "%s", type_name);
746 return result_buf;
749 bool is_variable_size(uint16_t vtype)
751 bool result;
752 switch(vtype) {
753 case VT_LPWSTR:
754 case VT_COMPRESSED_LPWSTR:
755 case VT_BSTR:
756 case VT_BLOB:
757 case VT_BLOB_OBJECT:
758 case VT_VARIANT:
759 result = true;
760 break;
761 default:
762 result = false;
763 break;
765 return result;
768 const char *get_store_status(uint8_t status_byte)
770 const char *result;
771 switch(status_byte) {
772 case 0:
773 result = "StoreStatusOk";
774 break;
775 case 1:
776 result = "StoreStatusDeferred";
777 break;
778 case 2:
779 result = "StoreStatusNull";
780 break;
781 default:
782 result = "Unknown Status";
783 break;
785 return result;
788 void set_variant_lpwstr(TALLOC_CTX *ctx,
789 struct wsp_cbasestoragevariant *vvalue,
790 const char *string_val)
792 vvalue->vtype = VT_LPWSTR;
793 vvalue->vvalue.vt_lpwstr.value = talloc_strdup(ctx, string_val);
796 void set_variant_i4(TALLOC_CTX *ctx,
797 struct wsp_cbasestoragevariant *vvalue,
798 uint32_t val)
800 vvalue->vtype = VT_I4;
801 vvalue->vvalue.vt_i4 = val;
804 void set_variant_vt_bool(TALLOC_CTX *ctx,
805 struct wsp_cbasestoragevariant *variant,
806 bool bval)
808 variant->vtype = VT_BOOL;
809 variant->vvalue.vt_bool = bval;
812 static void fill_int32_vec(TALLOC_CTX* ctx,
813 int32_t **pdest,
814 int32_t* ivector, uint32_t elems)
816 int i;
817 int32_t *dest = talloc_zero_array(ctx, int32_t, elems);
818 for ( i = 0; i < elems; i++ ) {
819 dest[ i ] = ivector[ i ];
821 *pdest = dest;
824 void set_variant_i4_vector(TALLOC_CTX *ctx,
825 struct wsp_cbasestoragevariant *variant,
826 int32_t* ivector, uint32_t elems)
828 variant->vtype = VT_VECTOR | VT_I4;
829 variant->vvalue.vt_i4_vec.vvector_elements = elems;
830 fill_int32_vec(ctx, &variant->vvalue.vt_i4_vec.vvector_data, ivector, elems);
833 static void fill_string_vec(TALLOC_CTX* ctx,
834 struct wsp_cbasestoragevariant *variant,
835 const char **strings, uint16_t elems)
837 int i;
838 variant->vvalue.vt_lpwstr_v.vvector_elements = elems;
839 variant->vvalue.vt_lpwstr_v.vvector_data = talloc_zero_array(ctx,
840 struct vt_lpwstr,
841 elems);
843 for( i = 0; i < elems; i++ ) {
844 variant->vvalue.vt_lpwstr_v.vvector_data[ i ].value = talloc_strdup(ctx, strings[ i ]);
848 static void fill_bstr_vec(TALLOC_CTX *ctx,
849 struct vt_bstr **pvector,
850 const char **strings, uint16_t elems)
852 int i;
853 struct vt_bstr *vdata = talloc_zero_array(ctx, struct vt_bstr, elems);
855 for( i = 0; i < elems; i++ ) {
856 vdata [ i ].value = talloc_strdup(ctx, strings[ i ]);
858 *pvector = vdata;
861 void set_variant_bstr(TALLOC_CTX *ctx, struct wsp_cbasestoragevariant *variant,
862 const char *string_val)
864 variant->vtype = VT_BSTR;
865 variant->vvalue.vt_bstr.value = talloc_strdup(ctx, string_val);
868 void set_variant_lpwstr_vector(TALLOC_CTX *ctx,
869 struct wsp_cbasestoragevariant *variant,
870 const char **string_vals, uint32_t elems)
872 variant->vtype = VT_LPWSTR | VT_VECTOR;
873 fill_string_vec(ctx, variant, string_vals, elems);
876 void set_variant_array_bstr(TALLOC_CTX *ctx,
877 struct wsp_cbasestoragevariant *variant,
878 const char **string_vals, uint16_t elems)
880 variant->vtype = VT_BSTR | VT_ARRAY;
881 variant->vvalue.vt_bstr_array.cdims = 1;
882 variant->vvalue.vt_bstr_array.ffeatures = 0;
884 variant->vvalue.vt_bstr_array.rgsabound =
885 talloc_zero_array(ctx, struct safearraybound, 1);
887 variant->vvalue.vt_bstr_array.rgsabound[0].celements = elems;
888 variant->vvalue.vt_bstr_array.rgsabound[0].ilbound = 0;
889 variant->vvalue.vt_bstr_array.cbelements = 0;
890 fill_bstr_vec(ctx, &variant->vvalue.vt_bstr_array.vdata,
891 string_vals, elems);
893 * if cbelements is the num bytes per elem it kindof means each
894 * string in the array must be the same size ?
897 if (elems >0) {
898 variant->vvalue.vt_bstr_array.cbelements =
899 strlen_m_term(variant->vvalue.vt_bstr_array.vdata[0].value)*2;
903 /* create single dim array of vt_i4 */
904 void set_variant_array_i4(TALLOC_CTX *ctx,
905 struct wsp_cbasestoragevariant *variant,
906 int32_t *vals, uint16_t elems)
908 /* #TODO see if we can combine with other set_variant_array methods */
909 variant->vtype = VT_I4 | VT_ARRAY;
910 variant->vvalue.vt_i4_array.cdims = 1;
911 variant->vvalue.vt_i4_array.ffeatures = 0;
913 variant->vvalue.vt_i4_array.rgsabound =
914 talloc_zero_array(ctx, struct safearraybound, 1);
916 variant->vvalue.vt_i4_array.rgsabound[0].celements = elems;
917 variant->vvalue.vt_i4_array.rgsabound[0].ilbound = 0;
918 variant->vvalue.vt_i4_array.cbelements = sizeof(uint32_t);
919 fill_int32_vec(ctx, &variant->vvalue.vt_i4_array.vdata, vals, elems);