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