Line data Source code
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 "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"
30 :
31 : #define BUFFER_SIZE 1024000
32 : struct guidtopropmap_holder
33 : {
34 : struct guidtopropmap *guidtopropmaploc;
35 : };
36 :
37 : struct full_propset_info_list {
38 : struct full_propset_info_list *prev, *next;
39 : struct full_propset_info info;
40 : };
41 :
42 : struct guidtopropmap {
43 : struct guidtopropmap *prev, *next;
44 : struct GUID guid;
45 : struct full_propset_info_list *propset;
46 : };
47 :
48 0 : static struct guidtopropmap *find_guid_props(
49 : struct guidtopropmap_holder *holder,
50 : const struct GUID *guid)
51 : {
52 0 : struct guidtopropmap *mapitem;
53 0 : for (mapitem = holder->guidtopropmaploc; mapitem; mapitem = mapitem->next) {
54 0 : if (GUID_equal(guid, &mapitem->guid)) {
55 : return mapitem;
56 : }
57 : }
58 : return NULL;
59 : }
60 :
61 0 : static bool getbool(char *str)
62 : {
63 0 : char *cpy = talloc_strdup(NULL, str);
64 0 : bool result;
65 :
66 0 : trim_string(cpy, " ", " ");
67 0 : if (strequal("TRUE", cpy)) {
68 : result = true;
69 : } else {
70 0 : result = false;
71 : }
72 0 : TALLOC_FREE(cpy);
73 0 : return result;
74 : }
75 :
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}
94 : };
95 :
96 0 : static uint16_t getvtype(char *str, bool isvec)
97 : {
98 0 : uint16_t result = UINT16_MAX;
99 0 : int i;
100 0 : for (i = 0; i < ARRAY_SIZE(vtype_map); i++) {
101 0 : if (strequal(vtype_map[i].typename, str)) {
102 0 : result = vtype_map[i].type;
103 0 : if (isvec) {
104 0 : result |= VT_VECTOR;
105 : }
106 : break;
107 : }
108 : }
109 0 : return result;
110 : }
111 :
112 0 : static bool parse_csv_line(TALLOC_CTX *ctx,
113 : char **csvs, size_t num_values,
114 : struct guidtopropmap_holder *propmap_holder)
115 : {
116 0 : struct guidtopropmap *mapitem = NULL;
117 0 : struct full_propset_info_list *item = NULL;
118 :
119 0 : char *guid_str = NULL;
120 0 : struct GUID guid;
121 0 : bool ok;
122 :
123 0 : item = talloc_zero(ctx,
124 : struct full_propset_info_list);
125 0 : if (!item) {
126 : return false;
127 : }
128 :
129 0 : item->info.in_inverted_index = false;
130 0 : item->info.is_column = true;
131 0 : item->info.can_col_be_indexed = true;
132 :
133 0 : if (strlen(csvs[1])) {
134 0 : guid_str = talloc_strdup(ctx, csvs[1]);
135 : }
136 :
137 0 : if (!guid_str) {
138 0 : DBG_ERR("out of memory\n");
139 0 : return false;
140 : }
141 :
142 0 : if (!trim_string(guid_str, "{", "}")) {
143 : return false;
144 : }
145 :
146 0 : if (strlen(csvs[0])) {
147 0 : char *tmp = talloc_strdup(item, csvs[0]);
148 0 : trim_string(tmp, " ", " ");
149 0 : item->info.name = tmp;
150 : }
151 :
152 0 : if (strlen(csvs[2])) {
153 0 : item->info.id = atoi(csvs[2]);
154 : }
155 :
156 0 : if (strlen(csvs[3])) {
157 0 : item->info.in_inverted_index = getbool(csvs[3]);
158 : }
159 :
160 0 : if (strlen(csvs[4])) {
161 0 : item->info.is_column = getbool(csvs[4]);
162 : }
163 :
164 0 : if (strlen(csvs[5])) {
165 0 : item->info.can_col_be_indexed = getbool(csvs[5]);
166 : }
167 :
168 0 : if (strlen(csvs[6])) {
169 0 : bool isvec = false;
170 0 : uint16_t type;
171 0 : if (strlen(csvs[0])) {
172 0 : isvec = getbool(csvs[8]);
173 : }
174 0 : type = getvtype(csvs[6], isvec);
175 0 : if (type == UINT16_MAX) {
176 0 : DBG_ERR("failed to parse type\n");
177 0 : return false;
178 : }
179 0 : item->info.vtype = type;
180 : }
181 :
182 0 : ok = parse_guid_string(guid_str, &guid);
183 0 : if (!ok) {
184 : return false;
185 : }
186 :
187 0 : mapitem = find_guid_props(propmap_holder, &guid);
188 0 : if (!mapitem) {
189 0 : mapitem = talloc_zero(propmap_holder,
190 : struct guidtopropmap);
191 0 : if (!mapitem) {
192 : return false;
193 : }
194 0 : mapitem->guid = guid;
195 0 : DLIST_ADD_END(propmap_holder->guidtopropmaploc, mapitem);
196 : }
197 :
198 0 : talloc_steal(mapitem, item);
199 0 : DLIST_ADD_END(mapitem->propset, item);
200 : return true;
201 : }
202 :
203 0 : static bool parse_properties_line(TALLOC_CTX *ctx,
204 : const char* line,
205 : struct guidtopropmap_holder *propmap_holder)
206 : {
207 0 : int ret;
208 0 : int pos;
209 0 : char* strv = NULL;
210 0 : char** csv_line = NULL;
211 0 : char* t = NULL;
212 0 : size_t len;
213 :
214 0 : ret = strv_split(ctx,
215 : &strv,
216 : line,
217 : ",");
218 :
219 0 : if (ret != 0) {
220 0 : DBG_ERR("failed to split line\n");
221 0 : return false;
222 : }
223 :
224 0 : len = strv_count(strv);
225 :
226 0 : if (len < 9) {
227 0 : DBG_WARNING("skipping line as it doesn't have "
228 : "enough fields\n");
229 0 : return true;
230 : }
231 :
232 0 : csv_line = talloc_zero_array(ctx,
233 : char *,
234 : len);
235 :
236 0 : if (!csv_line) {
237 0 : DBG_ERR("out of memory\n");
238 0 : return false;
239 : }
240 0 : for (pos = 0; pos < talloc_array_length(csv_line); pos++) {
241 0 : t = strv_next(strv, t);
242 : /* the scraped property file can have a non ascii char */
243 0 : if (strlen(t) == 1 && *t == 0xa0) {
244 : csv_line[pos] = talloc_strdup(csv_line,
245 : "");
246 : } else {
247 0 : csv_line[pos] = talloc_strdup(csv_line,
248 : t);
249 : }
250 0 : trim_string(csv_line[pos], " ", " ");
251 : }
252 :
253 0 : if (!parse_csv_line(csv_line, csv_line, len, propmap_holder)) {
254 0 : DBG_ERR("failed to parse line\n");
255 0 : TALLOC_FREE(csv_line);
256 0 : return false;
257 : }
258 0 : TALLOC_FREE(csv_line);
259 0 : return true;
260 : }
261 :
262 0 : static bool parse_properties_csvfile(TALLOC_CTX *ctx,
263 : struct guidtopropmap_holder *propmap_holder,
264 : const char* filename)
265 : {
266 0 : char **lines = NULL;
267 0 : int numlines;
268 0 : int i;
269 :
270 0 : if (filename == NULL || strlen(filename) == 0) {
271 : return false;
272 : }
273 :
274 0 : lines = file_lines_load(filename,
275 : &numlines,
276 : BUFFER_SIZE,
277 : ctx);
278 0 : if (!lines) {
279 0 : DBG_ERR("Failed to load %s\n", filename);
280 0 : return false;
281 : }
282 0 : DBG_ERR("parsed %d lines\n", numlines);
283 :
284 0 : for (i = 0; i < numlines; i++) {
285 0 : TALLOC_CTX *line_ctx = talloc_init("line context");
286 0 : if (!line_ctx) {
287 0 : DBG_ERR("out of memory\n");
288 0 : return false;
289 : }
290 :
291 0 : trim_string(lines[i], " ", " ");
292 0 : if (lines[i][0] == '#') {
293 0 : DBG_WARNING("skipping comment at line %d.\n)", i);
294 0 : TALLOC_FREE(line_ctx);
295 0 : continue;
296 : }
297 :
298 0 : if (!parse_properties_line(line_ctx,
299 : lines[i],
300 : propmap_holder)) {
301 0 : DBG_ERR("Failed to parse line %d\n", i);
302 : }
303 0 : TALLOC_FREE(line_ctx);
304 : }
305 : return true;
306 : }
307 :
308 0 : static bool populate_map(struct guidtopropmap_holder *propmap_holder)
309 : {
310 0 : const char * path = NULL;
311 0 : path = lp_wsp_property_file();
312 :
313 : /* first populate the map from property file */
314 0 : if (path) {
315 0 : parse_properties_csvfile(propmap_holder, propmap_holder, path);
316 : }
317 :
318 0 : return true;
319 : }
320 :
321 0 : static struct guidtopropmap_holder *propmap(void)
322 : {
323 0 : static struct guidtopropmap_holder *holder = NULL;
324 :
325 0 : if (!holder) {
326 0 : holder = talloc_zero(NULL, struct guidtopropmap_holder);
327 0 : if (holder) {
328 0 : populate_map(holder);
329 : }
330 : }
331 :
332 0 : return holder;
333 : }
334 :
335 46 : const struct full_propset_info *get_propset_info_with_guid(
336 : const char *prop_name,
337 : struct GUID *propset_guid)
338 : {
339 46 : const struct full_propset_info *result = NULL;
340 46 : struct guidtopropmap_holder *holder = NULL;
341 46 : struct guidtopropmap *mapitem = NULL;
342 :
343 46 : size_t i;
344 46 : const struct full_guid_propset *guid_propset = NULL;
345 :
346 : /* search builtin props first */
347 4561 : for (i = 0; full_propertyset[i].prop_info != NULL; i++) {
348 : const struct full_propset_info *item = NULL;
349 14442 : guid_propset = &full_propertyset[i];
350 : item = guid_propset->prop_info;
351 14442 : while (item->id) {
352 9927 : if (strequal(prop_name, item->name)) {
353 46 : *propset_guid = guid_propset->guid;
354 46 : result = item;
355 46 : break;
356 : }
357 9881 : item++;
358 : }
359 4561 : if (result) {
360 : break;
361 : }
362 : }
363 :
364 46 : if (result) {
365 : return result;
366 : }
367 :
368 : /* if we didn't find a match in builtin props try the extra props */
369 0 : holder = propmap();
370 0 : for (mapitem = holder->guidtopropmaploc; mapitem;
371 0 : mapitem = mapitem->next) {
372 0 : struct full_propset_info_list *propitem;
373 0 : for (propitem = mapitem->propset; propitem;
374 0 : propitem = propitem->next) {
375 0 : if (strequal(prop_name, propitem->info.name)) {
376 0 : *propset_guid = mapitem->guid;
377 0 : result = &propitem->info;
378 0 : break;
379 : }
380 : }
381 : }
382 : return result;
383 : }
384 :
385 3 : const struct full_propset_info *get_prop_info(const char *prop_name)
386 : {
387 3 : const struct full_propset_info *result = NULL;
388 3 : struct GUID guid;
389 3 : result = get_propset_info_with_guid(prop_name, &guid);
390 3 : return result;
391 : }
392 :
393 32 : char *prop_from_fullprop(TALLOC_CTX *ctx, struct wsp_cfullpropspec *fullprop)
394 : {
395 32 : size_t i;
396 32 : char *result = NULL;
397 32 : const struct full_propset_info *item = NULL;
398 32 : const struct full_propset_info_list *prop_item = NULL;
399 32 : bool search_by_id = (fullprop->ulkind == PRSPEC_PROPID);
400 32 : struct guidtopropmap_holder *holder = NULL;
401 32 : struct guidtopropmap *mapitem = NULL;
402 :
403 : /* check builtin properties */
404 3260 : for (i = 0; full_propertyset[i].prop_info != NULL; i++) {
405 : /* find propset */
406 3260 : if (GUID_equal(&fullprop->guidpropset,
407 : &full_propertyset[i].guid)) {
408 : item = full_propertyset[i].prop_info;
409 : break;
410 : }
411 : }
412 32 : if (item) {
413 227 : while (item->id) {
414 227 : if (search_by_id) {
415 227 : if( fullprop->name_or_id.prspec == item->id) {
416 32 : result = talloc_strdup(ctx, item->name);
417 32 : break;
418 : }
419 0 : } else if (strcmp(item->name,
420 : fullprop->name_or_id.propname.vstring)
421 : == 0) {
422 0 : result = talloc_strdup(ctx, item->name);
423 0 : break;
424 : }
425 195 : item++;
426 : }
427 : }
428 :
429 : /* not found, search the extra props */
430 32 : if (!result) {
431 0 : holder = propmap();
432 :
433 0 : for (mapitem = holder->guidtopropmaploc; mapitem;
434 0 : mapitem = mapitem->next) {
435 0 : if (GUID_equal(&fullprop->guidpropset,
436 0 : &mapitem->guid)) {
437 0 : prop_item = mapitem->propset;
438 0 : break;
439 : }
440 : }
441 :
442 0 : for (;prop_item; prop_item = prop_item->next) {
443 0 : if (search_by_id) {
444 0 : if(fullprop->name_or_id.prspec ==
445 0 : prop_item->info.id) {
446 0 : result = talloc_strdup(ctx,
447 0 : prop_item->info.name);
448 0 : break;
449 : }
450 0 : } else if (strcmp(prop_item->info.name,
451 : fullprop->name_or_id.propname.vstring) == 0) {
452 0 : result = talloc_strdup(ctx,
453 : prop_item->info.name);
454 0 : break;
455 : }
456 : }
457 : }
458 :
459 32 : if (!result) {
460 0 : result = GUID_string(ctx, &fullprop->guidpropset);
461 :
462 0 : if (search_by_id) {
463 0 : result = talloc_asprintf(result, "%s/%d", result,
464 : fullprop->name_or_id.prspec);
465 : } else {
466 0 : result = talloc_asprintf(result, "%s/%s", result,
467 : fullprop->name_or_id.propname.vstring);
468 : }
469 : }
470 32 : return result;
471 : }
472 :
473 2 : const char *genmeth_to_string(uint32_t genmethod)
474 : {
475 2 : const char *result = NULL;
476 2 : switch (genmethod) {
477 : case 0:
478 : result = "equals";
479 : break;
480 1 : case 1:
481 1 : result = "starts with";
482 1 : break;
483 0 : case 2:
484 0 : result = "matches inflection";
485 0 : break;
486 0 : default:
487 0 : result = NULL;
488 0 : break;
489 : }
490 2 : return result;
491 : }
492 :
493 32 : bool is_operator(struct wsp_crestriction *restriction) {
494 32 : bool result;
495 32 : switch(restriction->ultype) {
496 : case RTAND:
497 : case RTOR:
498 : case RTNOT:
499 : result = true;
500 : break;
501 32 : default:
502 32 : result = false;
503 32 : break;
504 : }
505 32 : return result;
506 : }
507 :
508 32 : const char *op_as_string(struct wsp_crestriction *restriction)
509 : {
510 32 : const char *op = NULL;
511 32 : if (is_operator(restriction)) {
512 0 : switch(restriction->ultype) {
513 0 : case RTAND:
514 0 : op = " && ";
515 0 : break;
516 0 : case RTOR:
517 0 : op = " || ";
518 0 : break;
519 0 : case RTNOT:
520 0 : op = "!";
521 0 : break;
522 : }
523 32 : } else if (restriction->ultype == RTPROPERTY) {
524 30 : struct wsp_cpropertyrestriction *prop_restr =
525 : &restriction->restriction.cpropertyrestriction;
526 30 : switch (prop_restr->relop & 0XF) {
527 15 : case PREQ:
528 15 : op = "=";
529 15 : break;
530 2 : case PRNE:
531 2 : op = "!=";
532 2 : break;
533 5 : case PRGE:
534 5 : op = ">=";
535 5 : break;
536 2 : case PRLE:
537 2 : op = "<=";
538 2 : break;
539 4 : case PRLT:
540 4 : op = "<";
541 4 : break;
542 2 : case PRGT:
543 2 : op = ">";
544 2 : break;
545 : default:
546 : break;
547 : }
548 2 : } else if (restriction->ultype == RTCONTENT) {
549 2 : struct wsp_ccontentrestriction *content = NULL;
550 2 : content = &restriction->restriction.ccontentrestriction;
551 2 : op = genmeth_to_string(content->ulgeneratemethod);
552 0 : } else if (restriction->ultype == RTNATLANGUAGE) {
553 0 : op = "=";
554 : }
555 32 : return op;
556 : }
557 :
558 0 : struct wsp_cfullpropspec *get_full_prop(struct wsp_crestriction *restriction)
559 : {
560 0 : struct wsp_cfullpropspec *result;
561 0 : switch (restriction->ultype) {
562 0 : case RTPROPERTY:
563 0 : result = &restriction->restriction.cpropertyrestriction.property;
564 0 : break;
565 0 : case RTCONTENT:
566 0 : result = &restriction->restriction.ccontentrestriction.property;
567 0 : break;
568 0 : case RTNATLANGUAGE:
569 0 : result = &restriction->restriction.cnatlanguagerestriction.property;
570 0 : break;
571 : default:
572 : result = NULL;
573 : break;
574 : }
575 0 : return result;
576 : }
577 :
578 30 : const char *variant_as_string(TALLOC_CTX *ctx,
579 : struct wsp_cbasestoragevariant *value, bool quote)
580 : {
581 30 : const char* result = NULL;
582 30 : switch(value->vtype) {
583 0 : case VT_UI1:
584 0 : result = talloc_asprintf(ctx, "%u",
585 0 : value->vvalue.vt_ui1);
586 0 : break;
587 0 : case VT_INT:
588 : case VT_I4:
589 0 : result = talloc_asprintf(ctx, "%d",
590 : value->vvalue.vt_i4);
591 0 : break;
592 0 : case VT_ERROR:
593 : case VT_UINT:
594 : case VT_UI4:
595 0 : result = talloc_asprintf(ctx, "%u",
596 : value->vvalue.vt_ui4);
597 0 : break;
598 0 : case VT_UI2:
599 : case VT_I2:
600 0 : result = talloc_asprintf(ctx, "%u",
601 0 : value->vvalue.vt_ui2);
602 0 : break;
603 0 : case VT_BOOL:
604 0 : result = talloc_asprintf(ctx, "%s",
605 0 : value->vvalue.vt_ui2 == 0xFFFF ?
606 : "true" : "false");
607 0 : break;
608 0 : case VT_DATE:
609 : case VT_FILETIME: {
610 0 : NTTIME filetime = value->vvalue.vt_ui8;
611 0 : time_t unixtime;
612 0 : struct tm *tm = NULL;
613 0 : char datestring[256];
614 0 : unixtime = nt_time_to_unix(filetime);
615 0 : tm = gmtime(&unixtime);
616 0 : strftime(datestring, sizeof(datestring), "%FT%TZ", tm);
617 0 : result = talloc_strdup(ctx, datestring);
618 0 : break;
619 : }
620 : case VT_R4: {
621 0 : float f;
622 0 : if (sizeof(f) != sizeof(value->vvalue.vt_ui4)) {
623 : DBG_ERR("can't convert float\n");
624 : break;
625 : }
626 0 : memcpy((void*)&f,
627 0 : (void*)&value->vvalue.vt_ui4,
628 : sizeof(value->vvalue.vt_ui4));
629 0 : result = talloc_asprintf(ctx, "%f",
630 : f);
631 0 : break;
632 : }
633 : case VT_R8: {
634 : /* should this really be unsigned ? */
635 0 : double dval;
636 0 : if (sizeof(dval) != sizeof(value->vvalue.vt_i8)) {
637 : DBG_ERR("can't convert double\n");
638 : break;
639 : }
640 0 : memcpy((void*)&dval,
641 0 : (void*)&value->vvalue.vt_i8,
642 : sizeof(dval));
643 0 : result = talloc_asprintf(ctx, "%f",
644 : dval);
645 0 : break;
646 : }
647 0 : case VT_I8: {
648 0 : result = talloc_asprintf(ctx, "%" PRIi64,
649 : value->vvalue.vt_i8);
650 0 : break;
651 : }
652 17 : case VT_UI8: {
653 17 : result = talloc_asprintf(ctx, "%" PRIu64,
654 : value->vvalue.vt_ui8);
655 17 : break;
656 : }
657 4 : case VT_LPWSTR:
658 4 : result = talloc_asprintf(ctx, "%s%s%s",
659 : quote ? "\'" : "",
660 : value->vvalue.vt_lpwstr.value,
661 : quote ? "\'" : "");
662 4 : break;
663 9 : case VT_LPWSTR | VT_VECTOR: {
664 9 : int num_elems =
665 9 : value->vvalue.vt_lpwstr_v.vvector_elements;
666 9 : int i;
667 18 : for(i = 0; i < num_elems; i++) {
668 9 : struct vt_lpwstr_vec *vec;
669 9 : const char *val;
670 9 : vec = &value->vvalue.vt_lpwstr_v;
671 9 : val = vec->vvector_data[i].value;
672 9 : result =
673 27 : talloc_asprintf(ctx,
674 : "%s%s%s%s%s",
675 : result ? result : "",
676 : i ? "," : "",
677 : quote ? "\'" : "",
678 : val,
679 : quote ? "\'" : "");
680 : }
681 : break;
682 : }
683 0 : default:
684 0 : DBG_INFO("can't represent unsupported vtype 0x%x as string\n",
685 : value->vtype);
686 : break;
687 : }
688 30 : return result;
689 : }
690 :
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"},
724 : };
725 :
726 0 : const char *get_vtype_name(uint32_t type)
727 : {
728 0 : const char *type_name = NULL;
729 0 : static char result_buf[255];
730 0 : int i;
731 0 : uint32_t temp = type & ~(VT_VECTOR | VT_ARRAY);
732 0 : for (i = 0; i < ARRAY_SIZE(typename_map); i++) {
733 0 : if (temp == typename_map[i].id) {
734 0 : type_name = typename_map[i].name;
735 0 : break;
736 : }
737 : }
738 0 : if (type & VT_VECTOR) {
739 0 : snprintf(result_buf, sizeof(result_buf), "Vector | %s", type_name);
740 0 : } else if (type & VT_ARRAY) {
741 0 : snprintf(result_buf, sizeof(result_buf), "Array | %s", type_name);
742 : } else {
743 0 : snprintf(result_buf, sizeof(result_buf), "%s", type_name);
744 : }
745 0 : return result_buf;
746 : }
747 :
748 0 : bool is_variable_size(uint16_t vtype)
749 : {
750 0 : bool result;
751 0 : 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 0 : default:
761 0 : result = false;
762 0 : break;
763 : }
764 0 : return result;
765 : }
766 :
767 0 : const char *get_store_status(uint8_t status_byte)
768 : {
769 0 : const char *result;
770 0 : switch(status_byte) {
771 : case 0:
772 : result = "StoreStatusOk";
773 : break;
774 0 : case 1:
775 0 : result = "StoreStatusDeferred";
776 0 : break;
777 0 : case 2:
778 0 : result = "StoreStatusNull";
779 0 : break;
780 0 : default:
781 0 : result = "Unknown Status";
782 0 : break;
783 : }
784 0 : return result;
785 : }
786 :
787 4 : void set_variant_lpwstr(TALLOC_CTX *ctx,
788 : struct wsp_cbasestoragevariant *vvalue,
789 : const char *string_val)
790 : {
791 4 : vvalue->vtype = VT_LPWSTR;
792 4 : vvalue->vvalue.vt_lpwstr.value = talloc_strdup(ctx, string_val);
793 4 : }
794 :
795 0 : void set_variant_i4(TALLOC_CTX *ctx,
796 : struct wsp_cbasestoragevariant *vvalue,
797 : uint32_t val)
798 : {
799 0 : vvalue->vtype = VT_I4;
800 0 : vvalue->vvalue.vt_i4 = val;
801 0 : }
802 :
803 0 : void set_variant_vt_bool(TALLOC_CTX *ctx,
804 : struct wsp_cbasestoragevariant *variant,
805 : bool bval)
806 : {
807 0 : variant->vtype = VT_BOOL;
808 0 : variant->vvalue.vt_bool = bval;
809 0 : }
810 :
811 0 : static void fill_int32_vec(TALLOC_CTX* ctx,
812 : int32_t **pdest,
813 : int32_t* ivector, uint32_t elems)
814 : {
815 0 : int i;
816 0 : int32_t *dest = talloc_zero_array(ctx, int32_t, elems);
817 0 : for ( i = 0; i < elems; i++ ) {
818 0 : dest[ i ] = ivector[ i ];
819 : }
820 0 : *pdest = dest;
821 0 : }
822 :
823 0 : void set_variant_i4_vector(TALLOC_CTX *ctx,
824 : struct wsp_cbasestoragevariant *variant,
825 : int32_t* ivector, uint32_t elems)
826 : {
827 0 : variant->vtype = VT_VECTOR | VT_I4;
828 0 : variant->vvalue.vt_i4_vec.vvector_elements = elems;
829 0 : fill_int32_vec(ctx, &variant->vvalue.vt_i4_vec.vvector_data, ivector, elems);
830 0 : }
831 :
832 9 : static void fill_string_vec(TALLOC_CTX* ctx,
833 : struct wsp_cbasestoragevariant *variant,
834 : const char **strings, uint16_t elems)
835 : {
836 9 : int i;
837 9 : variant->vvalue.vt_lpwstr_v.vvector_elements = elems;
838 9 : variant->vvalue.vt_lpwstr_v.vvector_data = talloc_zero_array(ctx,
839 : struct vt_lpwstr,
840 : elems);
841 :
842 18 : for( i = 0; i < elems; i++ ) {
843 9 : variant->vvalue.vt_lpwstr_v.vvector_data[ i ].value = talloc_strdup(ctx, strings[ i ]);
844 : }
845 9 : }
846 :
847 0 : static void fill_bstr_vec(TALLOC_CTX *ctx,
848 : struct vt_bstr **pvector,
849 : const char **strings, uint16_t elems)
850 : {
851 0 : int i;
852 0 : struct vt_bstr *vdata = talloc_zero_array(ctx, struct vt_bstr, elems);
853 :
854 0 : for( i = 0; i < elems; i++ ) {
855 0 : vdata [ i ].value = talloc_strdup(ctx, strings[ i ]);
856 : }
857 0 : *pvector = vdata;
858 0 : }
859 :
860 0 : void set_variant_bstr(TALLOC_CTX *ctx, struct wsp_cbasestoragevariant *variant,
861 : const char *string_val)
862 : {
863 0 : variant->vtype = VT_BSTR;
864 0 : variant->vvalue.vt_bstr.value = talloc_strdup(ctx, string_val);
865 0 : }
866 :
867 9 : void set_variant_lpwstr_vector(TALLOC_CTX *ctx,
868 : struct wsp_cbasestoragevariant *variant,
869 : const char **string_vals, uint32_t elems)
870 : {
871 9 : variant->vtype = VT_LPWSTR | VT_VECTOR;
872 9 : fill_string_vec(ctx, variant, string_vals, elems);
873 9 : }
874 :
875 0 : void set_variant_array_bstr(TALLOC_CTX *ctx,
876 : struct wsp_cbasestoragevariant *variant,
877 : const char **string_vals, uint16_t elems)
878 : {
879 0 : variant->vtype = VT_BSTR | VT_ARRAY;
880 0 : variant->vvalue.vt_bstr_array.cdims = 1;
881 0 : variant->vvalue.vt_bstr_array.ffeatures = 0;
882 :
883 0 : variant->vvalue.vt_bstr_array.rgsabound =
884 0 : talloc_zero_array(ctx, struct safearraybound, 1);
885 :
886 0 : variant->vvalue.vt_bstr_array.rgsabound[0].celements = elems;
887 0 : variant->vvalue.vt_bstr_array.rgsabound[0].ilbound = 0;
888 0 : variant->vvalue.vt_bstr_array.cbelements = 0;
889 0 : fill_bstr_vec(ctx, &variant->vvalue.vt_bstr_array.vdata,
890 : string_vals, elems);
891 : /*
892 : * if cbelements is the num bytes per elem it kindof means each
893 : * string in the array must be the same size ?
894 : */
895 :
896 0 : if (elems >0) {
897 0 : variant->vvalue.vt_bstr_array.cbelements =
898 0 : strlen_m_term(variant->vvalue.vt_bstr_array.vdata[0].value)*2;
899 : }
900 0 : }
901 :
902 : /* create single dim array of vt_i4 */
903 0 : void set_variant_array_i4(TALLOC_CTX *ctx,
904 : struct wsp_cbasestoragevariant *variant,
905 : int32_t *vals, uint16_t elems)
906 : {
907 : /* #TODO see if we can combine with other set_variant_array methods */
908 0 : variant->vtype = VT_I4 | VT_ARRAY;
909 0 : variant->vvalue.vt_i4_array.cdims = 1;
910 0 : variant->vvalue.vt_i4_array.ffeatures = 0;
911 :
912 0 : variant->vvalue.vt_i4_array.rgsabound =
913 0 : talloc_zero_array(ctx, struct safearraybound, 1);
914 :
915 0 : variant->vvalue.vt_i4_array.rgsabound[0].celements = elems;
916 0 : variant->vvalue.vt_i4_array.rgsabound[0].ilbound = 0;
917 0 : variant->vvalue.vt_i4_array.cbelements = sizeof(uint32_t);
918 0 : fill_int32_vec(ctx, &variant->vvalue.vt_i4_array.vdata, vals, elems);
919 0 : }
|