lib: Give lib/util/util_file.c its own header file
[samba.git] / librpc / wsp / wsp_util.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *
4  *  Window Search Service
5  *
6  *  Copyright (c) Noel Power
7  *
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.
12  *
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.
17  *
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/>.
20  */
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"
31
32 #define BUFFER_SIZE  1024000
33 struct guidtopropmap_holder
34 {
35         struct guidtopropmap *guidtopropmaploc;
36 };
37
38 struct full_propset_info_list {
39         struct full_propset_info_list *prev, *next;
40         struct full_propset_info info;
41 };
42
43 struct guidtopropmap {
44         struct guidtopropmap *prev, *next;
45         struct GUID guid;
46         struct full_propset_info_list *propset;
47 };
48
49 static struct guidtopropmap *find_guid_props(
50                 struct guidtopropmap_holder *holder,
51                 const struct GUID *guid)
52 {
53         struct guidtopropmap *mapitem;
54         for (mapitem = holder->guidtopropmaploc; mapitem; mapitem = mapitem->next) {
55                 if (GUID_equal(guid, &mapitem->guid)) {
56                         return mapitem;
57                 }
58         }
59         return NULL;
60 }
61
62 static bool getbool(char *str)
63 {
64         char *cpy = talloc_strdup(NULL, str);
65         bool result;
66
67         trim_string(cpy, " ", " ");
68         if (strequal("TRUE", cpy)) {
69                 result = true;
70         } else {
71                 result = false;
72         }
73         TALLOC_FREE(cpy);
74         return result;
75 }
76
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}
95 };
96
97 static uint16_t getvtype(char *str, bool isvec)
98 {
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;
106                         }
107                         break;
108                 }
109         }
110         return result;
111 }
112
113 static bool parse_csv_line(TALLOC_CTX *ctx,
114                 char **csvs, size_t num_values,
115                 struct guidtopropmap_holder *propmap_holder)
116 {
117         struct guidtopropmap *mapitem = NULL;
118         struct full_propset_info_list *item = NULL;
119
120         char *guid_str = NULL;
121         struct GUID guid;
122         bool ok;
123
124         item = talloc_zero(ctx,
125                         struct full_propset_info_list);
126         if (!item) {
127                 return false;
128         }
129
130         item->info.in_inverted_index = false;
131         item->info.is_column = true;
132         item->info.can_col_be_indexed = true;
133
134         if (strlen(csvs[1])) {
135                 guid_str = talloc_strdup(ctx, csvs[1]);
136         }
137
138         if (!guid_str) {
139                 DBG_ERR("out of memory\n");
140                 return false;
141         }
142
143         if (!trim_string(guid_str, "{", "}")) {
144                 return false;
145         }
146
147         if (strlen(csvs[0])) {
148                 char *tmp = talloc_strdup(item, csvs[0]);
149                 trim_string(tmp, " ", " ");
150                 item->info.name = tmp;
151         }
152
153         if (strlen(csvs[2])) {
154                 item->info.id = atoi(csvs[2]);
155         }
156
157         if (strlen(csvs[3])) {
158                 item->info.in_inverted_index = getbool(csvs[3]);
159         }
160
161         if (strlen(csvs[4])) {
162                 item->info.is_column = getbool(csvs[4]);
163         }
164
165         if (strlen(csvs[5])) {
166                 item->info.can_col_be_indexed = getbool(csvs[5]);
167         }
168
169         if (strlen(csvs[6])) {
170                 bool isvec = false;
171                 uint16_t type;
172                 if (strlen(csvs[0])) {
173                         isvec = getbool(csvs[8]);
174                 }
175                 type = getvtype(csvs[6], isvec);
176                 if (type == UINT16_MAX) {
177                         DBG_ERR("failed to parse type\n");
178                         return false;
179                 }
180                 item->info.vtype = type;
181         }
182
183         ok = parse_guid_string(guid_str, &guid);
184         if (!ok) {
185                 return false;
186         }
187
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;
194                 }
195                 mapitem->guid = guid;
196                 DLIST_ADD_END(propmap_holder->guidtopropmaploc, mapitem);
197         }
198
199         talloc_steal(mapitem, item);
200         DLIST_ADD_END(mapitem->propset, item);
201         return true;
202 }
203
204 static bool parse_properties_line(TALLOC_CTX *ctx,
205                 const char* line,
206                 struct guidtopropmap_holder *propmap_holder)
207 {
208         int ret;
209         int pos;
210         char* strv = NULL;
211         char** csv_line = NULL;
212         char* t = NULL;
213         size_t len;
214
215         ret = strv_split(ctx,
216                         &strv,
217                         line,
218                         ",");
219
220         if (ret != 0) {
221                 DBG_ERR("failed to split line\n");
222                 return false;
223         }
224
225         len = strv_count(strv);
226
227         if (len < 9) {
228                 DBG_WARNING("skipping line as it doesn't have "
229                             "enough fields\n");
230                 return true;
231         }
232
233         csv_line = talloc_zero_array(ctx,
234                         char *,
235                         len);
236
237         if (!csv_line) {
238                 DBG_ERR("out of memory\n");
239                 return false;
240         }
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,
249                                                 t);
250                 }
251                 trim_string(csv_line[pos], " ", " ");
252         }
253
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;
258         }
259         TALLOC_FREE(csv_line);
260         return true;
261 }
262
263 static bool parse_properties_csvfile(TALLOC_CTX *ctx,
264                 struct guidtopropmap_holder *propmap_holder,
265                 const char* filename)
266 {
267         char **lines = NULL;
268         int numlines;
269         int i;
270
271         if (filename == NULL || strlen(filename) == 0) {
272                 return false;
273         }
274
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;
282         }
283         DBG_ERR("parsed %d lines\n", numlines);
284
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;
290                 }
291
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;
297                 }
298
299                 if (!parse_properties_line(line_ctx,
300                                         lines[i],
301                                         propmap_holder)) {
302                         DBG_ERR("Failed to parse line %d\n", i);
303                 }
304                 TALLOC_FREE(line_ctx);
305         }
306         return true;
307 }
308
309 static bool populate_map(struct guidtopropmap_holder *propmap_holder)
310 {
311         const char * path = NULL;
312         path = lp_wsp_property_file();
313
314         /* first populate the map from property file */
315         if (path) {
316                 parse_properties_csvfile(propmap_holder, propmap_holder, path);
317         }
318
319         return true;
320 }
321
322 static struct guidtopropmap_holder *propmap(void)
323 {
324         static struct guidtopropmap_holder *holder = NULL;
325
326         if (!holder) {
327                 holder = talloc_zero(NULL, struct guidtopropmap_holder);
328                 if (holder) {
329                         populate_map(holder);
330                 }
331         }
332
333         return holder;
334 }
335
336 const struct full_propset_info *get_propset_info_with_guid(
337                                                 const char *prop_name,
338                                                 struct GUID *propset_guid)
339 {
340         const struct full_propset_info *result = NULL;
341         struct guidtopropmap_holder *holder = NULL;
342         struct guidtopropmap *mapitem = NULL;
343
344         size_t i;
345         const struct full_guid_propset *guid_propset = NULL;
346
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;
357                         }
358                         item++;
359                 }
360                 if (result) {
361                         break;
362                 }
363         }
364
365         if (result) {
366                 return result;
367         }
368
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;
380                         }
381                 }
382         }
383         return result;
384 }
385
386 const struct full_propset_info *get_prop_info(const char *prop_name)
387 {
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;
392 }
393
394 char *prop_from_fullprop(TALLOC_CTX *ctx, struct wsp_cfullpropspec *fullprop)
395 {
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;
403
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;
411                 }
412         }
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;
419                                 }
420                         } else if (strcmp(item->name,
421                                         fullprop->name_or_id.propname.vstring)
422                                         == 0) {
423                                 result = talloc_strdup(ctx, item->name);
424                                 break;
425                         }
426                         item++;
427                 }
428         }
429
430         /* not found, search the extra props */
431         if (!result) {
432                 holder = propmap();
433
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;
440                         }
441                 }
442
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;
450                                 }
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;
456                         }
457                 }
458         }
459
460         if (!result) {
461                 result = GUID_string(ctx, &fullprop->guidpropset);
462
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);
469                 }
470         }
471         return result;
472 }
473
474 const char *genmeth_to_string(uint32_t genmethod)
475 {
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;
490         }
491         return result;
492 }
493
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;
505         }
506         return result;
507 }
508
509 const char *op_as_string(struct wsp_crestriction *restriction)
510 {
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;
523                 }
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;
548                 }
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 = "=";
555         }
556         return op;
557 }
558
559 struct wsp_cfullpropspec *get_full_prop(struct wsp_crestriction *restriction)
560 {
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;
575         }
576         return result;
577 }
578
579 const char *variant_as_string(TALLOC_CTX *ctx,
580                         struct wsp_cbasestoragevariant *value, bool quote)
581 {
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;
620                 }
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;
626                         }
627                         memcpy((void*)&f,
628                                 (void*)&value->vvalue.vt_ui4,
629                                 sizeof(value->vvalue.vt_ui4));
630                         result = talloc_asprintf(ctx, "%f",
631                                                  f);
632                         break;
633                 }
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;
640                         }
641                         memcpy((void*)&dval,
642                                 (void*)&value->vvalue.vt_i8,
643                                 sizeof(dval));
644                         result = talloc_asprintf(ctx, "%f",
645                                                  dval);
646                         break;
647                 }
648                 case VT_I8: {
649                         result = talloc_asprintf(ctx, "%" PRIi64,
650                                                  value->vvalue.vt_i8);
651                         break;
652                 }
653                 case VT_UI8: {
654                         result = talloc_asprintf(ctx, "%" PRIu64,
655                                                  value->vvalue.vt_ui8);
656                         break;
657                 }
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 ? "\'" : "");
681                         }
682                         break;
683                 }
684                 default:
685                         DBG_INFO("can't represent unsupported vtype 0x%x as string\n",
686                                 value->vtype);
687                         break;
688         }
689         return result;
690 }
691
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"},
725 };
726
727 const char *get_vtype_name(uint32_t type)
728 {
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;
737                 }
738         }
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);
745         }
746         return result_buf;
747 }
748
749 bool is_variable_size(uint16_t vtype)
750 {
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;
764         }
765         return result;
766 }
767
768 const char *get_store_status(uint8_t status_byte)
769 {
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;
784         }
785         return result;
786 }
787
788 void set_variant_lpwstr(TALLOC_CTX *ctx,
789                         struct wsp_cbasestoragevariant *vvalue,
790                         const char *string_val)
791 {
792         vvalue->vtype = VT_LPWSTR;
793         vvalue->vvalue.vt_lpwstr.value = talloc_strdup(ctx, string_val);
794 }
795
796 void set_variant_i4(TALLOC_CTX *ctx,
797                     struct wsp_cbasestoragevariant *vvalue,
798                     uint32_t val)
799 {
800         vvalue->vtype = VT_I4;
801         vvalue->vvalue.vt_i4 = val;
802 }
803
804 void set_variant_vt_bool(TALLOC_CTX *ctx,
805                         struct wsp_cbasestoragevariant *variant,
806                         bool bval)
807 {
808         variant->vtype = VT_BOOL;
809         variant->vvalue.vt_bool = bval;
810 }
811
812 static void fill_int32_vec(TALLOC_CTX* ctx,
813                             int32_t **pdest,
814                             int32_t* ivector, uint32_t elems)
815 {
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 ];
820         }
821         *pdest = dest;
822 }
823
824 void set_variant_i4_vector(TALLOC_CTX *ctx,
825                            struct wsp_cbasestoragevariant *variant,
826                            int32_t* ivector, uint32_t elems)
827 {
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);
831 }
832
833 static void fill_string_vec(TALLOC_CTX* ctx,
834                                 struct wsp_cbasestoragevariant *variant,
835                                 const char **strings, uint16_t elems)
836 {
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);
842
843         for( i = 0; i < elems; i++ ) {
844                 variant->vvalue.vt_lpwstr_v.vvector_data[ i ].value = talloc_strdup(ctx, strings[ i ]);
845         }
846 }
847
848 static void fill_bstr_vec(TALLOC_CTX *ctx,
849                   struct vt_bstr **pvector,
850                   const char **strings, uint16_t elems)
851 {
852         int i;
853         struct vt_bstr *vdata = talloc_zero_array(ctx, struct vt_bstr, elems);
854
855         for( i = 0; i < elems; i++ ) {
856                 vdata [ i ].value = talloc_strdup(ctx, strings[ i ]);
857         }
858         *pvector = vdata;
859 }
860
861 void set_variant_bstr(TALLOC_CTX *ctx, struct wsp_cbasestoragevariant *variant,
862                         const char *string_val)
863 {
864         variant->vtype = VT_BSTR;
865         variant->vvalue.vt_bstr.value = talloc_strdup(ctx, string_val);
866 }
867
868 void set_variant_lpwstr_vector(TALLOC_CTX *ctx,
869                               struct wsp_cbasestoragevariant *variant,
870                               const char **string_vals, uint32_t elems)
871 {
872         variant->vtype = VT_LPWSTR | VT_VECTOR;
873         fill_string_vec(ctx, variant, string_vals, elems);
874 }
875
876 void set_variant_array_bstr(TALLOC_CTX *ctx,
877                            struct wsp_cbasestoragevariant *variant,
878                            const char **string_vals, uint16_t elems)
879 {
880         variant->vtype = VT_BSTR | VT_ARRAY;
881         variant->vvalue.vt_bstr_array.cdims = 1;
882         variant->vvalue.vt_bstr_array.ffeatures = 0;
883
884         variant->vvalue.vt_bstr_array.rgsabound =
885                 talloc_zero_array(ctx, struct safearraybound, 1);
886
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);
892         /*
893          * if cbelements is the num bytes per elem it kindof means each
894          * string in the array must be the same size ?
895          */
896
897         if (elems >0) {
898                 variant->vvalue.vt_bstr_array.cbelements =
899                         strlen_m_term(variant->vvalue.vt_bstr_array.vdata[0].value)*2;
900         }
901 }
902
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)
907 {
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;
912
913         variant->vvalue.vt_i4_array.rgsabound =
914                 talloc_zero_array(ctx, struct safearraybound, 1);
915
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);
920 }